似乎我们总是可以使用&:+
。为什么inject
在:+
必须map
时需要&:to_s
?如果原因是map
不能采用符号但必须采取阻止,那么map
是否也采用符号会有意义吗?
[1,3,5].inject(:+) # => 9
[1,3,5].inject(&:+) # => 9
[1,3,5].map(&:to_s) # => ["1", "3", "5"]
[1,3,5].map(:to_s) # => ArgumentError: wrong number of arguments (1 for 0)
答案 0 :(得分:4)
这是设计的。 inject
允许使用替代语法来获取符号,而map
始终需要一个块。
inject
中允许使用符号参数但map
中不允许的原因是因为inject
总是返回生成的迭代对象,而map
旨在返回块不存在时的Enumerator
实例。如果块不存在,如果必须查看是否提供了符号参数以决定是返回Enumerator
还是映射的Array
实例,则会变得复杂。因此,Ruby设计者为map
等方法制定了一个简单的规则,即缺少一个块意味着返回值为Enumerator
。
具有讽刺意味的是,inject
允许符号的一个缺点是,符号不能作为inject
中的初始值传递。但很可能,Ruby的设计者决定使用这种情况很少见。
答案 1 :(得分:4)
这是设计的。具体来说,inject
/ reduce
不需要完整的符号到proc语法(&:+
),而是只允许传递符号(:+
)(不同的行为)。
请注意,在这种特定情况下,传递符号与传递从符号派生的proc不同。
通过应用由 a block 或 a symbol 指定的二进制操作来组合枚举的所有元素,该操作命名方法或运算符。
如果指定一个块,那么对于枚举中的每个元素,该块将传递一个累加器值(memo)和该元素。如果您指定了符号,则集合中的每个元素都将传递给命名的备忘录方法。在任何一种情况下,结果都将成为备忘录的新值。在迭代结束时,memo的最终值是方法的返回值。