2015-12-30 93 views
3

看来我们总是可以使用&:+。为什么inject需要:+map必须采取&:to_s?如果原因是map不能采取符号,但必须采取一个块,那么如果map也需要一个符号是否有意义?为什么我们可以说`arr.inject(:+)`,但不得不说`arr.map(&:to_s)`?

[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

@ user2864740我在另一篇文章中看到,':to_s'返回块 –

+0

考虑,你可以写'arr.inject(:+)'或'arr.inject(:+)',考虑改变你的问题是为什么[Enumerable#map](http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-map)没有允许参数为符号的表单,作为[Enumerable#inject](http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-inject)(又名'reduce')。这不是你的意思吗? –

+0

是的,如果'inject'可以带一个符号,那么为什么它不是,至少在上面的例子中,'map'也是一个符号呢? –

回答

4

它是由设计。 inject允许替代语法采取符号,而map总是需要一个块。

可能的原因符号参数是允许在inject但不是在map是因为inject总是返回得到的迭代的对象,而map被设计为当一个块是不存在返回一个Enumerator实例。如果该块不存在,如果必须查看是否提供符号参数以决定是返回Enumerator还是映射的Array实例,则会变得复杂。因此,Ruby设计人员对诸如map之类的方法做了一个简单的规则,即块的缺失意味着返回值将是Enumerator

具有讽刺意味的是,inject允许符号的缺点是符号不能作为inject中的初始值传递。但是,Ruby的设计者可能会认为这种情况很罕见。

+1

':to_s'也是一个符号。请提供适用的参考资料/实例来说明行为。 – user2864740

+0

@sawa是否有缺点,如果'地图'也可以采取一个符号? –

+1

认真思考。只有'inject'允许它是一个符号的参数才有一个很好的理由。 (我不知道。) –

4

这是设计。具体来说,inject/reduce不需要完整的symbol-to-proc语法(&:+),但它们允许只传递一个符号(:+)(这是一种不同的行为)。

请注意,在这种特定情况下,传递符号与传递从符号派生的proc不同。

From the Ruby documentation

通过施加二进制运算,通过符号名称的方法或操作者指定的结合了枚举的所有元素。

如果指定一个块,那么对于enum中的每个元素,该块将传递一个累加器值(备注)和该元素。如果您改为指定一个符号,则集合中的每个元素都将被传递给指定的备忘录方法。无论哪种情况,结果都会成为备忘录的新值。在迭代结束时,备忘录的最终值是该方法的返回值。

+0

我想OP想知道为什么'map'不允许它的参数是一个符号。 –

+2

@CarySwoveland如果是这样的话,这是隐含在我的回应。但为了以防万一,这是回应。他的假设是':+'和'&:+'是相同的东西,而不是。前者是一个象征,后者是一个符号的过程。 'map'不接受符号,因为该方法被设计为接受block/proc而不是符号。 –

+0

哦,我确实说过:“如果原因是地图不能带符号但必须挡住一块,那么如果地图也需要一个符号,它会有意义吗?” –

相关问题