【问题标题】:Why doesn't Ruby inject return an enumerator?为什么 Ruby 注入不返回枚举器?
【发布时间】:2015-02-06 14:26:48
【问题描述】:

我期待Enumerable#inject 会像其他方法一样返回一个枚举器并传递一个块;但它抛出错误。在pry 中尝试了以下操作:

>> numbers = (1..12)
=> 1..12
>> numbers.each_with_index
=> #<Enumerator: ...>
>> numbers.each_with_index.map
=> #<Enumerator: ...>
>> numbers.inject(0)
TypeError: 0 is not a symbol
from (pry):18:in `inject'

我希望按如下方式使用它:

numbers = (1..12)
block = lambda { |sum, digit| sum + digit }

numbers.inject(0) { |sum, digit| sum + digit } # => 78
numbers.each_with_index.map &block # => [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]
numbers.inject(0) &block # => 0 is not a symbol (TypeError)

这样的实现有什么原因吗?

【问题讨论】:

  • 好问题。我以前没有考虑过。请注意,有很多Enumerable 方法可以使用一个块,但在没有给出枚举数时不返回枚举数。其他包括countmaxminminimaxnone?one?sort。我看到了他们所有人的共同点,包括reduce/inject
  • 感谢@CarySwoveland!我很困惑他们为什么选择这样实现它。我不相信它的概念,因为几乎没有进一步链接它的用例。我建议一致性可能会更好。
  • Enumerator 一次计算一个值。你可以拉一点(通过调用next)并且一个值会掉出来。您再次拉动,另一个值会掉出来。 inject 做不到。
  • @JörgWMittag 哇,这是一个完美的解释。谢谢!
  • 四点,Jikku:1) 如果reduce 返回了一个枚举器,并且您想对一个数组的值求和,总计7,您会返回[7].to_enum,在这种情况下您必须标记.next 才能检索它? (7.to_enum 不起作用,因为数字类没有 each.) 2)如果您需要返回枚举数,您可以经常使用其他方法,例如 each_with_object 作为 reduce 的替代品; (续)

标签: ruby enumerable


【解决方案1】:

从概念上讲,Enumerator 是一种集合。 Enumerable#inject 在集合的成员之间累积一个值,它返回 Enumerator 没有什么意义。

您可以通过将numbers.inject(0) &amp;block 更改为:

numbers.inject(0, &block)

【讨论】:

  • 不知道这两种调用方式有什么区别!我假设如果存在一个块,如果方法找到一个块,将被传递。
  • 是不是因为inject定义有block作为参数,而其他人可能正在使用yield来调用block?
【解决方案2】:

inject 这样的方法的重点是根据枚举器返回一些计算值。如果它们总是返回一个枚举器,那么就没有有意义的用法。当块不存在时它返回一个枚举器的原因是让您通过修改接收器来创建一个新的枚举器。但这不应该是最终目标;您只需创建一个枚举器,以便最终您可以根据它进行计算。

【讨论】:

  • 你确定它在没有块的情况下返回一个枚举器吗?例如,[1,2,3].reduce =&gt; LocalJumpError: no block given.
  • @CarySwoveland 我的意思是枚举数。
猜你喜欢
  • 2012-07-08
  • 2012-05-17
  • 2016-11-22
  • 1970-01-01
  • 2014-01-28
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多