Ruby
0 views
Two yields, one block
Question
What is the return value of the following Ruby code?
def sum
n = 0
n += yield
n += yield
n
end
sum { 42 } # => ???
The correct answer is
-
0 -
It raises
SyntaxError -
84Correct -
42
Explanation
TL;DR
yield invokes the block passed to the method, once per yield reached at runtime. The block { 42 } returns 42 on every invocation, so n goes from 0 to 42 to 84, and the method returns 84.
Step by step
def sum
n = 0
n += yield # n: 0 + 42
n += yield # n: 42 + 42
n
end
sum { 42 } # => 84
A block is not consumed by the first yield. It stays attached to the method call, and every yield runs it again:
def multiple_yields
yield
yield
end
multiple_yields { puts "multiple yields" }
Output:
multiple yields
multiple yields
Edge cases
yield accepts arguments, which become the block's parameters. Each invocation can pass different values:
def sum
n = 0
n += yield(1)
n += yield(10)
n
end
sum { |x| x * 2 } # => 22
Calling a method that yields without passing a block raises LocalJumpError:
def sum
n = 0
n += yield
n
end
begin
sum
rescue LocalJumpError => e
e.message # => "no block given (yield)"
end
Guard with block_given? when the block is optional:
def sum
return 0 unless block_given?
yield + yield
end
sum # => 0
sum { 21 } # => 42
Share this quiz
Comments
No comments yet. Be the first.