Blocks and Precedence
Mon Apr 14 09:48:00 UTC 2008
There are two different forms for passing a block to a method in Ruby, one with braces, and one with do/end. I used to think they were equivalent, but recently learned that there is a subtle difference having to do with precedence. As an example
def block_test(arg1)
"I received '#{arg1}' and " << (block_given? ? "a block which yielded '#{yield}'" : "no block")
end
def speak
"I've been told to say " << (block_given? ? yield : "nothing")
end
Looking at the brace form of passing blocks to methods, you can see that whether you surround your arguments with parentheses changes who gets the block
block_test speak { "hello" }
# => "I received 'I've been told to say hello' and no block"
block_test(speak) { "hello" }
# => "I received 'I've been told to say nothing' and a block which yielded 'hello'"
This is fairly intuitive. However, if you use the do/end form for the block, it gets passed as an argument to block_test whether you use parentheses or not
block_test speak do
"hello"
end
# => "I received 'I've been told to say nothing' and a block which yielded 'hello'"
block_test(speak) do
"hello"
end
# => "I received 'I've been told to say nothing' and a block which yielded 'hello'"