I am new to Ruby. I have used a lot of C# and JavaScript which allow higher-order functions and I typically use them on a daily basis.
Ruby seems a little strange to me though. An each function might look like:
def each
@items.each do |item|
yield(item)
end
end
items.each { |item| puts item }
Yet Ruby also has some support for higher-order functions. The above could be rewritten to something like:
def each(proc)
@items.each do |item|
proc.call item
end
end
items.each -> (item) { puts item } # Or...
items.each lambda { |item| puts item }
Or even:
def each(&proc)
@items.each do |item|
proc.call item
end
end
# No difference in syntax.
items.each { |item| puts item }
Which is more on par with most other languages, and is just a few characters longer. Instead of explicitly passing in a block, everything seems to use yield.
yield itself seems crazy, magical, and mysterious. After all, it’s going to the origin of the call and grabbing a block immediately following the call. This seems bizarre and unnatural, and I’m not aware of any parallel of this feature in another language.
So what’s the deal with yield?
Yield Passes Objects to a Method’s Block
Not really.
yieldpasses an argument to a block; it doesn’t “grab a block” or do anything with it. In other words, this:Here,
yieldisn’t doing anything but passing an argument to the block that is passed into thefoomethod. Every Ruby method supports an optional block—except when a block is actually mandatory—so the only “magic” is that the language allows a block to be passed even when it isn’t explicitly declared as part of the method signature.Further Examples
To see this implicit signature in action, consider this:
which will print “true” and return
nil, which is the expected return value from theputsmethod.Of course, without
yieldthe block doesn’t do anything at all. For example: