问题
I have a little question on passing block.
def a_method(a, b)
a + yield(a, b)
end
This works fine.
k = a_method(1, 2) do |x, y|
(x + y) * 3
end
puts k
But this won't work.
puts a_method(1, 2) do |x, y|
(x + y) * 3
end
# LocalJumpError: no block given (yield)
Can anyone kindly explain this to me?
Thanks. Example taken from Metaprogramming Ruby by Paolo Perrotta. Great book.
回答1:
The difference between do .. end
and curly braces is that the curly braces bind to the rightmost expression, while do .. end
bind to the leftmost one. Observe the following examples:
def first(x=nil)
puts " first(#{x.inspect}): #{block_given? ? "GOT BLOCK" : "no block"}"
"f"
end
def second(x=nil)
puts " second(#{x.inspect}): #{block_given? ? "GOT BLOCK" : "no block"}"
"s"
end
first second do |x| :ok end # second(nil): no block
# first("s"): GOT BLOCK
first second {|x| :ok } # second(nil): GOT BLOCK
# first("s"): no block
In the first case, the block made with do..end
will be bound to the first function (leftmost). In the second case the block made with curly brackets will be bound to the second function (rightmost).
Usually it's good idea to use parentheses if you have two functions and a block - just for readability and to avoid mistakes.
It's very easy to accidentally pass a block to puts
method, just as in your question.
回答2:
That's because the block is passed to puts
and not to a_method
.
This should do it:
puts (a_method(1, 2) { |x, y| (x + y) * 3 })
# if you want to keep it multilines
puts (a_method(1, 2) { |x, y|
(x + y) * 3
})
来源:https://stackoverflow.com/questions/10909496/passing-block-into-a-method-ruby