在Ruby中,为什么在使用"do"和"end"时不能将方法调用视为一个单元?

nop*_*ole 9 ruby methods syntax function

以下问题与" Ruby Print Inject Do Syntax " 问题有关.我的问题是,我们能坚持使用doend,使其与工作putsp

这有效:

a = [1,2,3,4]

b = a.inject do |sum, x|
  sum + x
end
puts b   # prints out 10
Run Code Online (Sandbox Code Playgroud)

所以,它是正确的,inject是Array对象的实例方法,并且此实例方法接受一段代码,然后返回一个数字.如果是这样,那么它应该与调用函数或方法并获取返回值没有什么不同:

b = foo(3)
puts b
Run Code Online (Sandbox Code Playgroud)

要么

b = circle.getRadius()
puts b
Run Code Online (Sandbox Code Playgroud)

在以上两种情况下,我们可以直接说

puts foo(3)
puts circle.getRadius()
Run Code Online (Sandbox Code Playgroud)

因此,使用以下两种方式无法直接使其工作:

a = [1,2,3,4]

puts a.inject do |sum, x|
  sum + x
end
Run Code Online (Sandbox Code Playgroud)

但它给了

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
Run Code Online (Sandbox Code Playgroud)

使用方法调用分组( )也不起作用:

a = [1,2,3,4]

puts (a.inject do |sum, x| 
        sum + x   
      end)
Run Code Online (Sandbox Code Playgroud)

这给了:

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)
         ^
Run Code Online (Sandbox Code Playgroud)

最后,以下版本有效:

a = [1,2,3,4]

puts a.inject { |sum, x|
    sum + x
}
Run Code Online (Sandbox Code Playgroud)

但为什么( )在前面的例子中没有使用work 的方法调用分组?如果程序员坚持使用do并且end可以使其工作,该怎么办?

out*_*tis 15

从(非官方的)ruby语法中,我们看到(...)in 的内容puts (...)必须是CALL_ARGS,而不是直接减少到STMT.但是,他们可以减少到'(' COMPSTMT ')'.通过包含一组额外的括号,您可以使用do ... end.

a = [1,2,3,4]

puts ((a.inject do |sum, x| 
         sum + x   
       end))
Run Code Online (Sandbox Code Playgroud)


Mar*_*off 7

这里的问题不只是你的括号:这是主要的空间 puts 括号.

随着代码

a = [1,2,3,4]

puts (a.inject do |sum, x|
             sum + x
                    end)
Run Code Online (Sandbox Code Playgroud)

我们得到您在问题中列出的语法错误.

如果你放下空间后puts,

a = [1,2,3,4]

puts(a.inject do |sum, x|
             sum + x
                    end)
Run Code Online (Sandbox Code Playgroud)

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表单具有更高的优先级,并且如果调用没有pare,则将绑定到最后一个参数.
  • do/end表单具有较低的优先级,即使没有parens也会绑定到调用.