Related
In some language such as Haskell, it is possible to use any function taking two arguments as an infix operator.
I find this notation interesting and would like to achieve the same in ruby.
Given a imaginary method or_if_familiar
I'd like to be able to write something like "omg" or_if_familiar "oh!" instead of or_if_familiar("omg", "oh!")
How one would create such a notation in ruby (without modifying ruby itself)?
A bit late to the party but I've been toying around with it and you can use operator overloading to create Infix operators just like in python (but with a bit more work), the syntax becomes a |op| b, here's how:
First a quick and dirty copy-paste to play around with Infix:
class Infix def initialize*a,&b;raise'arguments size mismatch'if a.length<0||a.length>3;raise'both method and b passed'if a.length!=0&&b;raise'no arguments passed'if a.length==0&&!b;#m=a.length>0? a[0].class==Symbol ? method(a[0]):a[0]:b;if a.length==3;#c=a[1];#s=a[2]end end;def|o;if#c;o.class==Infix ? self:#m.(#s,o)else;raise'missing first operand'end end;def coerce o;[Infix.new(#m,true,o),self]end;def v o;Infix.new(#m,true,o)end end;[NilClass,FalseClass,TrueClass,Object,Array].each{|c|c.prepend Module.new{def|o;o.class==Infix ? o.v(self):super end}};def Infix*a,&b;Infix.new *a,&b end
#
Ok
Step 1: create the Infix class
class Infix
def initialize *args, &block
raise 'error: arguments size mismatch' if args.length < 0 or args.length > 3
raise 'error: both method and block passed' if args.length != 0 and block
raise 'error: no arguments passed' if args.length == 0 and not block
#method = args.length > 0 ? args[0].class == Symbol ? method(args[0]) : args[0] : block
if args.length == 3; #coerced = args[1]; #stored_operand = args[2] end
end
def | other
if #coerced
other.class == Infix ? self : #method.call(#stored_operand, other)
else
raise 'error: missing first operand'
end
end
def coerce other
[Infix.new(#method, true, other), self]
end
def convert other
Infix.new(#method, true, other)
end
end
Step 2: fix all the classes that don't have a | method and the three special cases (true, false, and nil) (note: you can add any class in here and it will probably work fine)
[ NilClass, FalseClass, TrueClass,
Float, Symbol, String, Rational,
Complex, Hash, Array, Range, Regexp
].each {|c| c.prepend Module.new {
def | other
other.class == Infix ? other.convert(self) : super
end}}
Step 3: define your operators in one of 5 ways
# Lambda
pow = Infix.new -> (x, y) {x ** y}
# Block
mod = Infix.new {|x, y| x % y}
# Proc
avg = Infix.new Proc.new {|x, y| (x + y) / 2.0}
# Defining a method on the spot (the method stays)
pick = Infix.new def pick_method x, y
[x, y][rand 2]
end
# Based on an existing method
def diff_method x, y
(x - y).abs
end
diff = Infix.new :diff_method
Step 4: use them (spacing doesn't matter):
2 |pow| 3 # => 8
9|mod|4 # => 1
3| avg |6 # => 4.5
0 | pick | 1 # => 0 or 1 (randomly chosen)
You can even kinda sorta curry:
(This only works with the first operand)
diff_from_3 = 3 |diff
diff_from_3| 2 # => 1
diff_from_3| 4 # => 1
diff_from_3| -3 # => 6
As a bonus, this little method allows you to define Infixes (or any object really) without using .new:
def Infix *args, &block
Infix.new *args, &block
end
pow = Infix -> (x, y) {x ** y} # and so on
All that's left to do is wrap it up in a module
Hope this helped
P.S. You can muck about with the operators to have something like a <<op>> b, a -op- b, a >op> b and a <op<b for directionality, a **op** b for precedence and any other combination you want but beware when using true, false and nil as the first operand with logical operators (|, &&, not, etc.) as they tend to return before the infix operator is called.
For example: false |equivalent_of_or| 5 # => true if you don't correct.
FINALLY, run this to check a bunch of cases of all the builtin classes as both the first and second operand:
# pp prints both inputs
pp = Infix -> (x, y) {"x: #{x}\ny: #{y}\n\n"}
[ true, false, nil, 0, 3, -5, 1.5, -3.7, :e, :'3%4s', 'to',
/no/, /(?: [^A-g7-9]\s)(\w{2,3})*?/,
Rational(3), Rational(-9.5), Complex(1), Complex(0.2, -4.6),
{}, {e: 4, :u => 'h', 12 => [2, 3]},
[], [5, 't', :o, 2.2, -Rational(3)], (1..2), (7...9)
].each {|i| puts i.class; puts i |pp| i}
In Ruby, whether the operator is prefix or infix is fixed by the parser. Operator precedence is also fixed. There is no way, short of modifying the parser, of changing these things.
But you can implement the built-in operators for your objects
Although you may not change the fix-ness or precedence of a built-in operator, you may implement operators for your objects by defining methods. That is because Ruby translates operators into method calls. For example, this expression:
a + b
is translated into:
a.+(b)
Therefore, you may implement the + operator for an arbitrary object by defining the + method:
def +(rhs)
...
end
The prefix operator - causes a call to method #-, so to implement prefix - you do this:
def #-
..
end
You may also use methods
You may implement your own infix operators as plain methods. This will require a slightly different syntax than what you want. You want:
"omg" or_if_familiar "oh!"
Which you cannot have. What you can have is:
"omg".or_if_familiar "oh!"
This works because, in Ruby, the parentheses on method arguments may often be omitted. The above is equivalent to:
"omg".or_if_familiar("oh!")
In this example, we would implement this by monkey-patching the String class:
class String
def or_ir_familiar(rhs)
...
end
end
Ruby does not have infix method syntax, except for a fixed and predefined set of operators. And Ruby does not allow user code to change the language syntax. Ergo, what you want is not possible.
Based on Wayne Conrad's answer, I can write the following code that would work for any method defined in ruby top-level:
class Object
def method_missing(method, *args)
return super if args.size != 1
# only work if "method" method is defined in ruby top level
self.send(method, self, *args)
end
end
which allows to write
def much_greater_than(a,b)
a >= b * 10
end
"A very long sentence that say nothing really but should be long enough".much_greater_than "blah"
# or
42.much_greater_than 2
Thanks Wayne!
Interesting reference on the same subject:
Defining a new logical operator in Ruby
I was wondering, are &&, and, ||, or base core unchangeable functionalities (like in other languages e.g.: php) or are they object methods like & <=> but defined some magical way
More details on my trait of thoughts:
[] & [10]
# => []
[].&([10])
# => []
"aaa".& 10
# NoMethodError: undefined method `&' for "aaa":String
note it say undefined method
...of course you can do.
true.& false
# => false
...but you cannot do:
true.&& false
# SyntaxError:
so If it's possibility to do
class String
# monkey patch. If you googled this don't use this in real world, use ruby mixins insted
def &(right_side)
# do something meaningfull
right_side
end
end
"aaa".& 10
# => 10 # ta-da!
is there (with some magic) possible to do:
class String
# monkey patch. If you googled this don't use this in real world, use ruby mixins insted
def &&(right side)
# do something meaningfull
right side
end
end
# => SyntaxError: (irb):13: syntax error, unexpected keyword_end
thx
These are the operators that cannot be (re)defined:
&&, || (AND, OR)
.., ... (range)
?: (ternary)
rescue
= (and **=, &&=, &=, *=, +=. -=, <<=, >>= , ||=, |=, ^=)
defined?
not
and, or
if, unless, while, until
The others, like (incomplete list) !, ~, +, -, **, *, /, %, >>, ==, != are implemented as methods and can be redefined.
David A. Black stated in his book:
[T]he conditional assignment operator ||=, as well as its rarely spotted
cousin &&=, both of which provide the same kind of shortcut as the pseudooperator methods but are based on operators, namely || and &&, which you can’t override.
Now to get into the reason please Look and read Why can't we override||and&&? and Operator Overloading.
Everyone knows two of the ways to create an empty array: Array.new and []. The first one is 'standard', you might say, and the second one is simply syntax sugar. Many different objects such as Hash and maybe even String are shorthanded through this method.
My question is: Is there a way to define my own delimimers for objects? An example would be <>. Maybe an alias like '<' => 'MyObject.new(' and '>' => ')'?
[] is an array literal, {} is a hash literal. There are plenty of these shorthand forms in Ruby. Check this wikibook out for more information.
There is no object literal, but you can use (source):
a = Struct.new(:foo,:bar).new(34,89)
a.foo # 34
a.bar # 89
No. (And ew anyway.) Delimiters are part of the parse process.
You can define operators, like <; that's different than a delimiter. For example, you could redefine < to take a block, and use that block to create a class, or a method, etc. But... I don't think I would.
You could do:
class MyObject; end
def [](*args)
MyObject.new *args
end
# but you can't use it directly:
o = [] #=> [] (empty Array)
# you must to refer to self:
o = self[] #=> #<MyObject:0x1234567>
# but since self depends on where are you, you must assign self to a global variable:
$s = self
o = $s[]
# or to a constant:
S = self
o = S[]
# however, in that case it's better to do it in the proper class:
class << MyObject
def [](*args)
new *args
end
end
# and assign it to a single-letter constant to reduce characters:
S = MyObject
# so
o = S[] #=> #<MyObject:0x1234568>
I can't think on something more compact.
I am trying to understand the difference between these four methods. I know by default that == calls the method equal? which returns true when both operands refer to exactly the same object.
=== by default also calls == which calls equal?... okay, so if all these three methods are not overridden, then I guess
===, == and equal? do exactly the same thing?
Now comes eql?. What does this do (by default)? Does it make a call to the operand's hash/id?
Why does Ruby have so many equality signs? Are they supposed to differ in semantics?
I'm going to heavily quote the Object documentation here, because I think it has some great explanations. I encourage you to read it, and also the documentation for these methods as they're overridden in other classes, like String.
Side note: if you want to try these out for yourself on different objects, use something like this:
class Object
def all_equals(o)
ops = [:==, :===, :eql?, :equal?]
Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
end
end
"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}
== — generic "equality"
At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.
This is the most common comparison, and thus the most fundamental place where you (as the author of a class) get to decide if two objects are "equal" or not.
=== — case equality
For class Object, effectively the same as calling #==, but typically overridden by descendants to provide meaningful semantics in case statements.
This is incredibly useful. Examples of things which have interesting === implementations:
Range
Regex
Proc (in Ruby 1.9)
So you can do things like:
case some_object
when /a regex/
# The regex matches
when 2..4
# some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
# the lambda returned true
end
See my answer here for a neat example of how case+Regex can make code a lot cleaner. And of course, by providing your own === implementation, you can get custom case semantics.
eql? — Hash equality
The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden == method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:
1 == 1.0 #=> true
1.eql? 1.0 #=> false
So you're free to override this for your own uses, or you can override == and use alias :eql? :== so the two methods behave the same way.
equal? — identity comparison
Unlike ==, the equal? method should never be overridden by subclasses: it is used to determine object identity (that is, a.equal?(b) iff a is the same object as b).
This is effectively pointer comparison.
I love jtbandes answer, but since it is pretty long, I will add my own compact answer:
==, ===, eql?, equal?
are 4 comparators, ie. 4 ways to compare 2 objects, in Ruby.
As, in Ruby, all comparators (and most operators) are actually method-calls, you can change, overwrite, and define the semantics of these comparing methods yourself. However, it is important to understand, when Ruby's internal language constructs use which comparator:
== (value comparison)
Ruby uses :== everywhere to compare the values of 2 objects, eg. Hash-values:
{a: 'z'} == {a: 'Z'} # => false
{a: 1} == {a: 1.0} # => true
=== (case comparison)
Ruby uses :=== in case/when constructs. The following code snippets are logically identical:
case foo
when bar; p 'do something'
end
if bar === foo
p 'do something'
end
eql? (Hash-key comparison)
Ruby uses :eql? (in combination with the method hash) to compare Hash-keys. In most classes :eql? is identical with :==.
Knowledge about :eql? is only important, when you want to create your own special classes:
class Equ
attr_accessor :val
alias_method :initialize, :val=
def hash() self.val % 2 end
def eql?(other) self.hash == other.hash end
end
h = {Equ.new(3) => 3, Equ.new(8) => 8, Equ.new(15) => 15} #3 entries, but 2 are :eql?
h.size # => 2
h[Equ.new(27)] # => 15
Note: The commonly used Ruby-class Set also relies on Hash-key-comparison.
equal? (object identity comparison)
Ruby uses :equal? to check if two objects are identical. This method (of class BasicObject) is not supposed to be overwritten.
obj = obj2 = 'a'
obj.equal? obj2 # => true
obj.equal? obj.dup # => false
Equality operators: == and !=
The == operator, also known as equality or double equal, will return true if both objects are equal and false if they are not.
"koan" == "koan" # Output: => true
The != operator, also known as inequality, is the opposite of ==. It will return true if both objects are not equal and false if they are equal.
"koan" != "discursive thought" # Output: => true
Note that two arrays with the same elements in a different order are not equal, uppercase and lowercase versions of the same letter are not equal and so on.
When comparing numbers of different types (e.g., integer and float), if their numeric value is the same, == will return true.
2 == 2.0 # Output: => true
equal?
Unlike the == operator which tests if both operands are equal, the equal method checks if the two operands refer to the same object. This is the strictest form of equality in Ruby.
Example:
a = "zen"
b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
In the example above, we have two strings with the same value. However, they are two distinct objects, with different object IDs. Hence, the equal? method will return false.
Let's try again, only this time b will be a reference to a. Notice that the object ID is the same for both variables, as they point to the same object.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
eql?
In the Hash class, the eql? method it is used to test keys for equality. Some background is required to explain this. In the general context of computing, a hash function takes a string (or a file) of any size and generates a string or integer of fixed size called hashcode, commonly referred to as only hash. Some commonly used hashcode types are MD5, SHA-1, and CRC. They are used in encryption algorithms, database indexing, file integrity checking, etc. Some programming languages, such as Ruby, provide a collection type called hash table. Hash tables are dictionary-like collections which store data in pairs, consisting of unique keys and their corresponding values. Under the hood, those keys are stored as hashcodes. Hash tables are commonly referred to as just hashes. Notice how the word hashcan refer to a hashcode or to a hash table. In the context of Ruby programming, the word hash almost always refers to the dictionary-like collection.
Ruby provides a built-in method called hash for generating hashcodes. In the example below, it takes a string and returns a hashcode. Notice how strings with the same value always have the same hashcode, even though they are distinct objects (with different object IDs).
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
The hash method is implemented in the Kernel module, included in the Object class, which is the default root of all Ruby objects. Some classes such as Symbol and Integer use the default implementation, others like String and Hash provide their own implementations.
Symbol.instance_method(:hash).owner # Output: => Kernel
Integer.instance_method(:hash).owner # Output: => Kernel
String.instance_method(:hash).owner # Output: => String
Hash.instance_method(:hash).owner # Output: => Hash
In Ruby, when we store something in a hash (collection), the object provided as a key (e.g., string or symbol) is converted into and stored as a hashcode. Later, when retrieving an element from the hash (collection), we provide an object as a key, which is converted into a hashcode and compared to the existing keys. If there is a match, the value of the corresponding item is returned. The comparison is made using the eql? method under the hood.
"zen".eql? "zen" # Output: => true
# is the same as
"zen".hash == "zen".hash # Output: => true
In most cases, the eql? method behaves similarly to the == method. However, there are a few exceptions. For instance, eql? does not perform implicit type conversion when comparing an integer to a float.
2 == 2.0 # Output: => true
2.eql? 2.0 # Output: => false
2.hash == 2.0.hash # Output: => false
Case equality operator: ===
Many of Ruby's built-in classes, such as String, Range, and Regexp, provide their own implementations of the === operator, also known as case-equality, triple equals or threequals. Because it's implemented differently in each class, it will behave differently depending on the type of object it was called on. Generally, it returns true if the object on the right "belongs to" or "is a member of" the object on the left. For instance, it can be used to test if an object is an instance of a class (or one of its subclasses).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
The same result can be achieved with other methods which are probably best suited for the job. It's usually better to write code that is easy to read by being as explicit as possible, without sacrificing efficiency and conciseness.
2.is_a? Integer # Output: => true
2.kind_of? Integer # Output: => true
2.instance_of? Integer # Output: => false
Notice the last example returned false because integers such as 2 are instances of the Fixnum class, which is a subclass of the Integer class. The ===, is_a? and instance_of? methods return true if the object is an instance of the given class or any subclasses. The instance_of method is stricter and only returns true if the object is an instance of that exact class, not a subclass.
The is_a? and kind_of? methods are implemented in the Kernel module, which is mixed in by the Object class. Both are aliases to the same method. Let's verify:
Kernel.instance_method(:kind_of?) == Kernel.instance_method(:is_a?) # Output: => true
Range Implementation of ===
When the === operator is called on a range object, it returns true if the value on the right falls within the range on the left.
(1..4) === 3 # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6 # Output: => false
("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false
Remember that the === operator invokes the === method of the left-hand object. So (1..4) === 3 is equivalent to (1..4).=== 3. In other words, the class of the left-hand operand will define which implementation of the === method will be called, so the operand positions are not interchangeable.
Regexp Implementation of ===
Returns true if the string on the right matches the regular expression on the left.
/zen/ === "practice zazen today" # Output: => true
# is the same as
"practice zazen today"=~ /zen/
Implicit usage of the === operator on case/when statements
This operator is also used under the hood on case/when statements. That is its most common use.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
In the example above, if Ruby had implicitly used the double equal operator (==), the range 10..20 would not be considered equal to an integer such as 15. They match because the triple equal operator (===) is implicitly used in all case/when statements. The code in the example above is equivalent to:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Pattern matching operators: =~ and !~
The =~ (equal-tilde) and !~ (bang-tilde) operators are used to match strings and symbols against regex patterns.
The implementation of the =~ method in the String and Symbol classes expects a regular expression (an instance of the Regexp class) as an argument.
"practice zazen" =~ /zen/ # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil
:zazen =~ /zen/ # Output: => 2
:zazen =~ /discursive thought/ # Output: => nil
The implementation in the Regexp class expects a string or a symbol as an argument.
/zen/ =~ "practice zazen" # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil
In all implementations, when the string or symbol matches the Regexp pattern, it returns an integer which is the position (index) of the match. If there is no match, it returns nil. Remember that, in Ruby, any integer value is "truthy" and nil is "falsy", so the =~ operator can be used in if statements and ternary operators.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Pattern-matching operators are also useful for writing shorter if statements. Example:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
The !~ operator is the opposite of =~, it returns true when there is no match and false if there is a match.
More info is available at this blog post.
I would like to expand on the === operator.
=== is not an equality operator!
Not.
Let's get that point really across.
You might be familiar with === as an equality operator in Javascript and PHP, but this just not an equality operator in Ruby and has fundamentally different semantics.
So what does === do?
=== is the pattern matching operator!
=== matches regular expressions
=== checks range membership
=== checks being instance of a class
=== calls lambda expressions
=== sometimes checks equality, but mostly it does not
So how does this madness make sense?
Enumerable#grep uses === internally
case when statements use === internally
Fun fact, rescue uses === internally
That is why you can use regular expressions and classes and ranges and even lambda expressions in a case when statement.
Some examples
case value
when /regexp/
# value matches this regexp
when 4..10
# value is in range
when MyClass
# value is an instance of class
when ->(value) { ... }
# lambda expression returns true
when a, b, c, d
# value matches one of a through d with `===`
when *array
# value matches an element in array with `===`
when x
# values is equal to x unless x is one of the above
end
All these example work with pattern === value too, as well as with grep method.
arr = ['the', 'quick', 'brown', 'fox', 1, 1, 2, 3, 5, 8, 13]
arr.grep(/[qx]/)
# => ["quick", "fox"]
arr.grep(4..10)
# => [5, 8]
arr.grep(String)
# => ["the", "quick", "brown", "fox"]
arr.grep(1)
# => [1, 1]
Ruby exposes several different methods for handling equality:
a.equal?(b) # object identity - a and b refer to the same object
a.eql?(b) # object equivalence - a and b have the same value
a == b # object equivalence - a and b have the same value with type conversion.
Continue reading by clicking the link below, it gave me a clear summarized understanding.
https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/equality-matchers
Hope it helps others.
=== #---case equality
== #--- generic equality
both works similar but "===" even do case statements
"test" == "test" #=> true
"test" === "test" #=> true
here the difference
String === "test" #=> true
String == "test" #=> false
.eql? - This operator returns true if the receiver and argument have both the same type and equal values.
for example - 10.eql?(10.0) is false.
=== - it will test equality in case statement.
for example - (1...10) === 1 is true
== - This operator checks whether the two given operands are equal or not. If equals, it returns TRUE, Otherwise it returns FALSE.
for example - (1...10) == 1 is false
for more example click here
I wrote a simple test for all the above.
def eq(a, b)
puts "#{[a, '==', b]} : #{a == b}"
puts "#{[a, '===', b]} : #{a === b}"
puts "#{[a, '.eql?', b]} : #{a.eql?(b)}"
puts "#{[a, '.equal?', b]} : #{a.equal?(b)}"
end
eq("all", "all")
eq(:all, :all)
eq(Object.new, Object.new)
eq(3, 3)
eq(1, 1.0)
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
Continuing the "Hidden features of ..." meme, let's share the lesser-known but useful features of Ruby programming language.
Try to limit this discussion with core Ruby, without any Ruby on Rails stuff.
See also:
Hidden features of C#
Hidden features of Java
Hidden features of JavaScript
Hidden features of Ruby on Rails
Hidden features of Python
(Please, just one hidden feature per answer.)
Thank you
From Ruby 1.9 Proc#=== is an alias to Proc#call, which means Proc objects can be used in case statements like so:
def multiple_of(factor)
Proc.new{|product| product.modulo(factor).zero?}
end
case number
when multiple_of(3)
puts "Multiple of 3"
when multiple_of(7)
puts "Multiple of 7"
end
Peter Cooper has a good list of Ruby tricks. Perhaps my favorite of his is allowing both single items and collections to be enumerated. (That is, treat a non-collection object as a collection containing just that object.) It looks like this:
[*items].each do |item|
# ...
end
Don't know how hidden this is, but I've found it useful when needing to make a Hash out of a one-dimensional array:
fruit = ["apple","red","banana","yellow"]
=> ["apple", "red", "banana", "yellow"]
Hash[*fruit]
=> {"apple"=>"red", "banana"=>"yellow"}
One trick I like is to use the splat (*) expander on objects other than Arrays. Here's an example on a regular expression match:
match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)
Other examples include:
a, b, c = *('A'..'Z')
Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom
Wow, no one mentioned the flip flop operator:
1.upto(100) do |i|
puts i if (i == 3)..(i == 15)
end
One of the cool things about ruby is that you can call methods and run code in places other languages would frown upon, such as in method or class definitions.
For instance, to create a class that has an unknown superclass until run time, i.e. is random, you could do the following:
class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample
end
RandomSubclass.superclass # could output one of 6 different classes.
This uses the 1.9 Array#sample method (in 1.8.7-only, see Array#choice), and the example is pretty contrived but you can see the power here.
Another cool example is the ability to put default parameter values that are non fixed (like other languages often demand):
def do_something_at(something, at = Time.now)
# ...
end
Of course the problem with the first example is that it is evaluated at definition time, not call time. So, once a superclass has been chosen, it stays that superclass for the remainder of the program.
However, in the second example, each time you call do_something_at, the at variable will be the time that the method was called (well, very very close to it)
Another tiny feature - convert a Fixnum into any base up to 36:
>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"
>> 1234567890.to_s(8)
=> "11145401322"
>> 1234567890.to_s(16)
=> "499602d2"
>> 1234567890.to_s(24)
=> "6b1230i"
>> 1234567890.to_s(36)
=> "kf12oi"
And as Huw Walters has commented, converting the other way is just as simple:
>> "kf12oi".to_i(36)
=> 1234567890
Hashes with default values! An array in this case.
parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []
parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"
Very useful in metaprogramming.
Another fun addition in 1.9 Proc functionality is Proc#curry which allows you to turn a Proc accepting n arguments into one accepting n-1. Here it is combined with the Proc#=== tip I mentioned above:
it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]
case Time.now
when it_is_saturday
puts "Saturday!"
when it_is_sunday
puts "Sunday!"
else
puts "Not the weekend"
end
Download Ruby 1.9 source, and issue make golf, then you can do things like this:
make golf
./goruby -e 'h'
# => Hello, world!
./goruby -e 'p St'
# => StandardError
./goruby -e 'p 1.tf'
# => 1.0
./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/ruby-svn/src/trunk"
Read the golf_prelude.c for more neat things hiding away.
Boolean operators on non boolean values.
&& and ||
Both return the value of the last expression evaluated.
Which is why the ||= will update the variable with the value returned expression on the right side if the variable is undefined. This is not explicitly documented, but common knowledge.
However the &&= isn't quite so widely known about.
string &&= string + "suffix"
is equivalent to
if string
string = string + "suffix"
end
It's very handy for destructive operations that should not proceed if the variable is undefined.
The Symbol#to_proc function that Rails provides is really cool.
Instead of
Employee.collect { |emp| emp.name }
You can write:
Employee.collect(&:name)
One final one - in ruby you can use any character you want to delimit strings. Take the following code:
message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"
If you don't want to escape the double-quotes within the string, you can simply use a different delimiter:
contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]
As well as avoiding having to escape delimiters, you can use these delimiters for nicer multiline strings:
sql = %{
SELECT strings
FROM complicated_table
WHERE complicated_condition = '1'
}
Use a Range object as an infinite lazy list:
Inf = 1.0 / 0
(1..Inf).take(5) #=> [1, 2, 3, 4, 5]
More info here: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby/
I find using the define_method command to dynamically generate methods to be quite interesting and not as well known. For example:
((0..9).each do |n|
define_method "press_#{n}" do
#number = #number.to_i * 10 + n
end
end
The above code uses the 'define_method' command to dynamically create the methods "press1" through "press9." Rather then typing all 10 methods which essentailly contain the same code, the define method command is used to generate these methods on the fly as needed.
module_function
Module methods that are declared as module_function will create copies of themselves as private instance methods in the class that includes the Module:
module M
def not!
'not!'
end
module_function :not!
end
class C
include M
def fun
not!
end
end
M.not! # => 'not!
C.new.fun # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>
If you use module_function without any arguments, then any module methods that comes after the module_function statement will automatically become module_functions themselves.
module M
module_function
def not!
'not!'
end
def yea!
'yea!'
end
end
class C
include M
def fun
not! + ' ' + yea!
end
end
M.not! # => 'not!'
M.yea! # => 'yea!'
C.new.fun # => 'not! yea!'
Short inject, like such:
Sum of range:
(1..10).inject(:+)
=> 55
Warning: this item was voted #1 Most Horrendous Hack of 2008, so use with care. Actually, avoid it like the plague, but it is most certainly Hidden Ruby.
Superators Add New Operators to Ruby
Ever want a super-secret handshake operator for some unique operation in your code? Like playing code golf? Try operators like
-~+~-
or
<---
That last one is used in the examples for reversing the order of an item.
I have nothing to do with the Superators Project beyond admiring it.
I'm late to the party, but:
You can easily take two equal-length arrays and turn them into a hash with one array supplying the keys and the other the values:
a = [:x, :y, :z]
b = [123, 456, 789]
Hash[a.zip(b)]
# => { :x => 123, :y => 456, :z => 789 }
(This works because Array#zip "zips" up the values from the two arrays:
a.zip(b) # => [[:x, 123], [:y, 456], [:z, 789]]
And Hash[] can take just such an array. I've seen people do this as well:
Hash[*a.zip(b).flatten] # unnecessary!
Which yields the same result, but the splat and flatten are wholly unnecessary--perhaps they weren't in the past?)
Auto-vivifying hashes in Ruby
def cnh # silly name "create nested hash"
Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }
This can just be damn handy.
Destructuring an Array
(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]
Where:
a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]
Using this technique we can use simple assignment to get the exact values we want out of nested array of any depth.
Class.new()
Create a new class at run time. The argument can be a class to derive from, and the block is the class body. You might also want to look at const_set/const_get/const_defined? to get your new class properly registered, so that inspect prints out a name instead of a number.
Not something you need every day, but quite handy when you do.
create an array of consecutive numbers:
x = [*0..5]
sets x to [0, 1, 2, 3, 4, 5]
A lot of the magic you see in Rubyland has to do with metaprogramming, which is simply writing code that writes code for you. Ruby's attr_accessor, attr_reader, and attr_writer are all simple metaprogramming, in that they create two methods in one line, following a standard pattern. Rails does a whole lot of metaprogramming with their relationship-management methods like has_one and belongs_to.
But it's pretty simple to create your own metaprogramming tricks using class_eval to execute dynamically-written code.
The following example allows a wrapper object to forwards certain methods along to an internal object:
class Wrapper
attr_accessor :internal
def self.forwards(*methods)
methods.each do |method|
define_method method do |*arguments, &block|
internal.send method, *arguments, &block
end
end
end
forwards :to_i, :length, :split
end
w = Wrapper.new
w.internal = "12 13 14"
w.to_i # => 12
w.length # => 8
w.split('1') # => ["", "2 ", "3 ", "4"]
The method Wrapper.forwards takes symbols for the names of methods and stores them in the methods array. Then, for each of those given, we use define_method to create a new method whose job it is to send the message along, including all arguments and blocks.
A great resource for metaprogramming issues is Why the Lucky Stiff's "Seeing Metaprogramming Clearly".
use anything that responds to ===(obj) for case comparisons:
case foo
when /baz/
do_something_with_the_string_matching_baz
when 12..15
do_something_with_the_integer_between_12_and_15
when lambda { |x| x % 5 == 0 }
# only works in Ruby 1.9 or if you alias Proc#call as Proc#===
do_something_with_the_integer_that_is_a_multiple_of_5
when Bar
do_something_with_the_instance_of_Bar
when some_object
do_something_with_the_thing_that_matches_some_object
end
Module (and thus Class), Regexp, Date, and many other classes define an instance method :===(other), and can all be used.
Thanks to Farrel for the reminder of Proc#call being aliased as Proc#=== in Ruby 1.9.
The "ruby" binary (at least MRI's) supports a lot of the switches that made perl one-liners quite popular.
Significant ones:
-n Sets up an outer loop with just "gets" - which magically works with given filename or STDIN, setting each read line in $_
-p Similar to -n but with an automatic puts at the end of each loop iteration
-a Automatic call to .split on each input line, stored in $F
-i In-place edit input files
-l Automatic call to .chomp on input
-e Execute a piece of code
-c Check source code
-w With warnings
Some examples:
# Print each line with its number:
ruby -ne 'print($., ": ", $_)' < /etc/irbrc
# Print each line reversed:
ruby -lne 'puts $_.reverse' < /etc/irbrc
# Print the second column from an input CSV (dumb - no balanced quote support etc):
ruby -F, -ane 'puts $F[1]' < /etc/irbrc
# Print lines that contain "eat"
ruby -ne 'puts $_ if /eat/i' < /etc/irbrc
# Same as above:
ruby -pe 'next unless /eat/i' < /etc/irbrc
# Pass-through (like cat, but with possible line-end munging):
ruby -p -e '' < /etc/irbrc
# Uppercase all input:
ruby -p -e '$_.upcase!' < /etc/irbrc
# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
ruby -i.bak -p -e '$_.upcase!' /etc/irbrc
Feel free to google "ruby one-liners" and "perl one-liners" for tons more usable and practical examples. It essentially allows you to use ruby as a fairly powerful replacement to awk and sed.
The send() method is a general-purpose method that can be used on any Class or Object in Ruby. If not overridden, send() accepts a string and calls the name of the method whose string it is passed. For example, if the user clicks the “Clr” button, the ‘press_clear’ string will be sent to the send() method and the ‘press_clear’ method will be called. The send() method allows for a fun and dynamic way to call functions in Ruby.
%w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
button btn, :width => 46, :height => 46 do
method = case btn
when /[0-9]/: 'press_'+btn
when 'Clr': 'press_clear'
when '=': 'press_equals'
when '+': 'press_add'
when '-': 'press_sub'
when '*': 'press_times'
when '/': 'press_div'
end
number.send(method)
number_field.replace strong(number)
end
end
I talk more about this feature in Blogging Shoes: The Simple-Calc Application
Fool some class or module telling it has required something that it really hasn't required:
$" << "something"
This is useful for example when requiring A that in turns requires B but we don't need B in our code (and A won't use it either through our code):
For example, Backgroundrb's bdrb_test_helper requires 'test/spec', but you don't use it at all, so in your code:
$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")
Defining a method that accepts any number of parameters and just discards them all
def hello(*)
super
puts "hello!"
end
The above hello method only needs to puts "hello" on the screen and call super - but since the superclass hello defines parameters it has to as well - however since it doesn't actually need to use the parameters itself - it doesn't have to give them a name.
private unless Rails.env == 'test'
# e.g. a bundle of methods you want to test directly
Looks like a cool and (in some cases) nice/useful hack/feature of Ruby.