“(1..4).inject(&:+)”在Ruby中是如何工作的

13

我觉得这段 Ruby 代码相当有趣

(1..4).inject(&:+)

好的,我知道inject的作用,我也知道这段代码基本上等同于

(1..4).inject(0) {|a,n| a + n}

但它到底是如何工作的?

为什么&:+和写{|a,n| a + n}块是相同的?

为什么它不需要一个初始值?我可以用0作为initial value,但是(1..4).inject(&:*)也可以,而那里必须有一个初始值为1...


8
这实际上是两个完全不同的问题,其中第一个问题是其他11个已经在StackOverflow上提出并回答的问题的重复:http://StackOverflow.Com/q/99318/ http://StackOverflow.Com/q/1217088/ http://StackOverflow.Com/q/1792683/ http://StackOverflow.Com/q/1961030/ http://StackOverflow.Com/q/2096975/ http://StackOverflow.Com/q/2211751/ http://StackOverflow.Com/q/2259775/ http://StackOverflow.Com/q/2388337/ http://StackOverflow.Com/q/2697024/ http://StackOverflow.Com/q/3888044/ http://StackOverflow.Com/q/4512587/ - Jörg W Mittag
1个回答

14

来自Ruby文档:

如果您指定一个符号,那么集合中的每个元素都将传递给memo的指定方法

因此,指定符号等同于传递以下块: {|memo, a| memo.send(sym, a)}

如果您没有明确为memo指定初始值,则使用集合的第一个元素作为memo的初始值。

因此,没有任何魔法,Ruby只是将第一个元素作为初始值,并从第二个元素开始注入。 您可以通过编写 [].inject(:+) 来检查它:它返回 nil 而不是 [].inject(0,:+),后者返回0。

编辑:我没有注意到&符号。您不需要它, inject 将使用符号。但是,如果您写了它,则该符号会转换为块,可以在其他方法中非常有用。


@tokland 这基本上是相同的转换,但适用于任何方法,在链接的问题中排名第一的答案有很好的解释。 - adamax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接