Precedence Rules

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.

Note

A method can test whether it has received a block using the block_given? method. You can find examples of this in the precedence.rb program.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.98.207