什么是:+和&:+在Ruby中?

Val*_*yev 38 ruby

我已经看过好几次,但我无法弄清楚如何使用它们.镐说这些是特殊的快捷方式,但我无法找到语法描述.

我在这样的背景下见过他们:

[1,2,3].inject(:+)
Run Code Online (Sandbox Code Playgroud)

以计算总和为例.

Kon*_*ase 68

让我们从一个更简单的例子开始.假设我们想要在大写字母中包含一系列字符串:

['foo', 'bar', 'blah'].map { |e| e.upcase }
# => ['FOO', 'BAR', 'BLAH']
Run Code Online (Sandbox Code Playgroud)

此外,您可以创建所谓的Proc对象(闭包):

block = proc { |e| e.upcase }
block.call("foo") # => "FOO"
Run Code Online (Sandbox Code Playgroud)

您可以使用&语法将此类proc传递给方法:

block = proc { |e| e.upcase }
['foo', 'bar', 'blah'].map(&block)
# => ['FOO', 'BAR', 'BLAH']
Run Code Online (Sandbox Code Playgroud)

这样做,是在块上调用to_proc然后为每个块调用它:

some_object = Object.new
def some_object.to_proc
  proc { |e| e.upcase }
end

['foo', 'bar', 'blah'].map(&some_object)
# => ['FOO', 'BAR', 'BLAH']
Run Code Online (Sandbox Code Playgroud)

现在,Rails首先将to_proc方法添加到Symbol中,后者已添加到ruby核心库中:

:whatever.to_proc # => proc { |e| e.whatever }
Run Code Online (Sandbox Code Playgroud)

因此你可以这样做:

['foo', 'bar', 'blah'].map(&:upcase)
# => ['FOO', 'BAR', 'BLAH']
Run Code Online (Sandbox Code Playgroud)

此外,Symbol#to_proc甚至更智能,因为它实际上执行以下操作:

:whatever.to_proc # => proc { |obj, *args| obj.send(:whatever, *args) }
Run Code Online (Sandbox Code Playgroud)

这意味着

[1, 2, 3].inject(&:+)
Run Code Online (Sandbox Code Playgroud)

等于

[1, 2, 3].inject { |a, b| a + b }
Run Code Online (Sandbox Code Playgroud)

  • `inject`也支持`[1,2,3] .inject(:+)`(注意你不需要&) (5认同)
  • 这不是ruby对注入的定义.inject不调用to_proc,它使用rb_funcall和给定的符号作为方法的名称.请参阅enum.c中的inject_op_i. (5认同)