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

时间:2010-04-23 07:59:43

标签: ruby

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

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

[1,2,3].inject(:+)
例如,

计算总和。

2 个答案:

答案 0 :(得分:68)

让我们从一个更简单的例子开始。 假设我们想要一个字符串数组:

['foo', 'bar', 'blah'].map { |e| e.upcase }
# => ['FOO', 'BAR', 'BLAH']

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

block = proc { |e| e.upcase }
block.call("foo") # => "FOO"

你可以将这样一个过程传递给一个带有&的方法。语法:

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

这样做是在块上调用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']

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

:whatever.to_proc # => proc { |e| e.whatever }

因此你可以这样做:

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

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

:whatever.to_proc # => proc { |obj, *args| obj.send(:whatever, *args) }

这意味着

[1, 2, 3].inject(&:+)

等于

[1, 2, 3].inject { |a, b| a + b }

答案 1 :(得分:2)

inject接受一个符号作为参数,该符号必须是方法或运算符的名称,在这种情况下为:+

所以[1,2,3].inject(:+)会将每个值传递给该符号指定的方法,从而将数组中的所有元素相加。

来源:https://ruby-doc.org/core-2.5.1/Enumerable.html