Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Block definition - difference between braces and do-end?

Tags:

ruby

block

can anybody explain why the following code aborts with an error

irb(main):186:0> print ((1..10).collect do |x| x**2 end)
SyntaxError: (irb):186: syntax error, unexpected keyword_do_block,
expecting ')'
print ((1..10).collect do |x| x**2 end)
                         ^
(irb):186: syntax error, unexpected keyword_end, expecting $end
print ((1..10).collect do |x| x**2 end)
                                      ^
        from /usr/bin/irb:12:in `<main>'

whereas following code with the same functionality works as expected ?

irb(main):187:0> print ((1..10).collect { |x| x**2 })
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]=> nil

I did believed curly-braces "{ }" can substitute "do end" arbitrarily at block definition.

I know I can "fix" the first call by omitting a space between print method and the first parenthesis, but I'm interested in an explanation why it behaves different.

like image 472
S1ackman Avatar asked May 30 '11 18:05

S1ackman


1 Answers

The difference is precedence:

# Equivalent to puts( (1..10).map { |i| i*2 } )
> puts (1..10).map { |i| i*2 }
2
4
6
8
10
12
14
16
18
20
 => nil 

# Equivalent to puts( (1..10).map ) { |i| i*2 }
> puts (1..10).map do |i| i*2 end
#<Enumerator:0x928f24>
 => nil 

In the first case, the block is passed to map, and everything works properly. In the second case, the block is passed to puts, which doesn't do anything with it. map doesn't receive a block and just returns an enumerator.

As for the syntax error, if you remove the space between print and ( everything works ;)

The difference is whether ruby is treating your parentheses as method argument delimiters, or whether it's a generic statement grouping. I'm not sure of the exact difference there but it's subtle and annoying

like image 160
Gareth Avatar answered Nov 15 '22 12:11

Gareth