开发者

Block definition - difference between braces and do-end?

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 ')'
pri开发者_运维技巧nt ((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.


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


There is an ultimate answer already on SO.

Unfortunately this is definitely not a good demonstration of least surprise philosophy behind Ruby.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜