【问题标题】:How to get size of cloned lazy enumerator如何获取克隆的惰性枚举器的大小
【发布时间】:2018-05-14 16:31:58
【问题描述】:

我们有一个 Enumerator::Lazy 对象

a = [1,2,3].lazy.map {} #=> <Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>
a.size #=> 3
a.clone.size #=> nil

有人对这种行为有正确的解释吗?我知道size 返回枚举器的大小,如果不能懒惰地计算,则返回 nil。 当我们克隆对象时,它会返回

a.clone #=> <Enumerator::Lazy:<Enumerator::Generator:0x00007fdaa80218d8>:each>

【问题讨论】:

  • 我不完全确定这里发生了什么,但我敢猜测这与Object#clone 执行的 副本有关。我认为甚至可能在惰性枚举器上执行深层复制(通常),并且正是枚举器的这种嵌套导致了异常行为。
  • 也许这应该被认为是 ruby​​ 中的一个(晦涩的)错误;我不知道。也许在bugs.ruby-lang.org 上提出这个问题,看看他们对此有何看法?
  • 似乎在最近的版本中引入了它,在 2.3.1 中按预期工作
  • 读者:如果不明显,“我知道 size 返回枚举数的大小,如果不能懒惰地计算,则返回 nil。”来自Enumerator#size 的文档。
  • 有一个相关的线程here,可能会感兴趣。

标签: ruby ruby-2.4


【解决方案1】:

我知道 size 返回枚举器的大小,如果不能懒惰地计算,则返回 nil。

size for a Enumerator 不一定是真实的东西(或至少不是人们认为的那样),这可能是实施此更改的原因。

例如

[1,2,3].to_enum.size
#=> nil

[1,2,3].to_enum(:each) { 1 }.size #=> 1
#=> 1

或者更好

[1,2,3].to_enum(:each) { "A" }.size 
#=> "A" 

当我们克隆对象时,它会返回 a.clone #=&gt; &lt;Enumerator::Lazy&lt;Enumerator::Generator:0x00007fdaa80218d8&gt;:each&gt;

这似乎是 2.4 中的一个变化,它似乎恢复为 :each 方法(可能通过enum_for),因为在 2.3 中,对map 的引用与大小一样被保留。显然由于反转没有发生迭代,并且无法以“懒惰”的方式确定大小,因此nil

【讨论】:

  • 因此,根据您的示例,这是一个 ruby​​ 错误(因为 size 必须只返回真实对象大小或 nil)。 Mb 你在bugs.ruby-lang.org 上打开一个问题?
  • @AlexFrolov 这不是文档所说的“可选参数可用于指定如何以惰性方式计算大小(请参阅#size)。它可以是值或可调用的目的。”延迟计算的含义由您决定
  • 我明白了。谢谢你的解释
猜你喜欢
  • 2012-11-07
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 2013-12-03
  • 2021-08-08
  • 2014-11-10
  • 1970-01-01
  • 2020-10-19
相关资源
最近更新 更多