块定义 - 大括号和do-end之间的区别?

时间:2011-05-30 18:05:56

标签: ruby block

任何人都可以解释为什么下面的代码会以错误中止

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>'

而具有相同功能的以下代码是否按预期工作?

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

我确实相信大括号“{}”可以在块上随意替换“do end” 定义

我知道我可以通过省略打印之间的空格来“修复”第一个调用 方法和第一个括号,但我对解释感兴趣 为什么它的行为不同。

2 个答案:

答案 0 :(得分:13)

区别优先:

# 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 

在第一种情况下,块传递给map,一切正常。 在第二种情况下,块传递给puts,它不对它做任何事情。 map没有收到块,只返回一个枚举器。

至于语法错误,如果删除print(之间的空格,一切正常;)

区别在于ruby是否将括号视为方法参数分隔符,或者它是否是通用语句分组。我不确定那里的确切差异,但它是微妙和恼人的

答案 1 :(得分:0)

在SO上已经有终极 answer

不幸的是,这绝对是很好地证明了Ruby背后最少的惊喜哲学。