Blocks within curly brackets have stronger precedence than blocks within do
and end
. Let’s see what that means in practice. Consider these two examples:
foo bar do |s| puts( s ) end foo bar{ |s| puts(s) }
Here, foo
and bar
are both methods, and the code between curly brackets and do
and end
are blocks. So, to which of the two methods is each of these blocks passed? It turns out that the do..end
block would be passed to the leftmost method, foo
, whereas the block in curly brackets would be sent to the rightmost method, bar
. This is because curly brackets are said to have higher precedence than do
and end
.
Consider this program:
precedence.rb
def foo( b ) puts("---in foo---") a = 'foo' if block_given? puts( "(Block passed to foo)" ) yield( a ) else puts( "(no block passed to foo)" ) end puts( "in foo, arg b = #{b}" ) return "returned by " << a end def bar puts("---in bar---") a = 'bar' if block_given? puts( "(Block passed to bar)" ) yield( a ) else puts( "(no block passed to bar)" ) end return "returned by " << a end foo bar do |s| puts( s ) end # 1) do..end block foo bar{ |s| puts(s) } # 2) {..} block
Here the do..end
block has lower precedence, and the method foo
is given priority. This means both bar
and the do..end
block are passed to foo
. Thus, these two expressions are equivalent:
foo bar do |s| puts( s ) end foo( bar ) do |s| puts( s ) end
A curly bracket block, on the other hand, has stronger precedence, so it tries to execute immediately and is passed to the first possible receiver method (bar
). The result (that is, the value returned by bar
) is then passed as an argument to foo
, but this time, foo
does not receive the block itself. Thus, the two following expressions are equivalent:
foo bar{ |s| puts(s) } foo( bar{ |s| puts(s) } )
If you are confused by all this, take comfort in that you are not alone! The potential ambiguities result from the fact that, in Ruby, the parentheses around argument lists are optional. As you can see from the alternative versions I gave earlier, the ambiguities disappear when you use parentheses.