在Ruby中,为什么在使用“do”和“end”时,方法调用不能被视为一个单元?
以下问题与“ Ruby Print Inject Do Syntax ”问题有关。 我的问题是,我们可以坚持使用do
和end
并使其与puts
或p
吗?
这有效:
a = [1,2,3,4] b = a.inject do |sum, x| sum + x end puts b # prints out 10
所以,是正确的说, inject
是Array对象的实例方法,这个实例方法接受一段代码,然后返回一个数字。 如果是这样,那么它应该与调用函数或方法并返回返回值没有什么不同:
b = foo(3) puts b
要么
b = circle.getRadius() puts b
在以上两种情况下,我们可以直接说
puts foo(3) puts circle.getRadius()
因此,无法通过以下两种方式直接使其工作:
a = [1,2,3,4] puts a.inject do |sum, x| sum + x end
但它给了
ch01q2.rb:7:in `inject': no block given (LocalJumpError) from ch01q2.rb:4:in `each' from ch01q2.rb:4:in `inject' from ch01q2.rb:4
使用( )
对方法调用进行分组也不起作用:
a = [1,2,3,4] puts (a.inject do |sum, x| sum + x end)
这给了:
ch01q3.rb:4: syntax error, unexpected kDO_BLOCK, expecting ')' puts (a.inject do |sum, x| ^ ch01q3.rb:4: syntax error, unexpected '|', expecting '=' puts (a.inject do |sum, x| ^ ch01q3.rb:6: syntax error, unexpected kEND, expecting $end end) ^
最后,以下版本有效:
a = [1,2,3,4] puts a.inject { |sum, x| sum + x }
但是为什么使用( )
的方法调用分组在前面的例子中不起作用? 如果程序员坚持他使用do
和end
,它可以被用来工作吗?
从(非官方) ruby语法中 ,我们看到puts (...)
中的puts (...)
必须是CALL_ARGS
,它们不会直接缩减为STMT
。 但是,它们可以缩减为'(' COMPSTMT ')'
。 通过包含一组额外的括号,您可以使用do ... end
。
a = [1,2,3,4] puts ((a.inject do |sum, x| sum + x end))
这里的问题不仅仅是你的括号:它主要是puts
括号之后的空格。
随着代码
a = [1,2,3,4] puts (a.inject do |sum, x| sum + x end)
我们得到您在问题中列出的语法错误。
如果你放弃之后puts
空间,
a = [1,2,3,4] puts(a.inject do |sum, x| sum + x end)
按预期打印10
。
最后,使用puts ((a.inject...
带空格和双括号也打印出10
,但通过ruby -cw XXX.rb
运行它告诉我们:
a.rb:5: warning: (...) interpreted as grouped expression
Syntax OK
ruby -cw
用于在打开完整的W arnings时查看语法。 当-cw
打开时,您将收到有关可疑括号和分组的警告。 我更习惯看到的错误是“不要在参数括号之前放置空格” – 所以不要这样做!
最后, a.inject do
没有括号但是a.inject {
工作的情况下失败的原因是,大括号的优先级高于do
/ end
。 作为一个非常粗略的准则,你可以说p a.map { foo }
等同于p(a.map do foo end)
; 和p a.map do foo end
相当于(p a.map) do foo end
,这当然不带块参数。
另请参阅块上的Ruby快速参考 (特别是最后两行):
块,闭包和过程
块/瓶盖
- 块必须遵循方法调用:
invocation do ... end
invocation { ... }
- 块记住它们的变量上下文,并且是完全闭包。
- 块通过yield调用,可以传递参数。
- Brace表单具有更高的优先级,如果调用没有parens,则将绑定到最后一个参数。
- do / end表单具有较低的优先级,即使没有parens也会绑定到调用。