如何为外部迭代创建“克隆”功能的枚举器? [英] How to create a "clone"-able enumerator for external iteration?

查看:74
本文介绍了如何为外部迭代创建“克隆”功能的枚举器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过 next (可以克隆),以便克隆保留当前的枚举状态。

I want to create an enumerator for external iteration via next that is clone-able, so that the clone retains the current enumeration state.

例如,假设我有一个返回枚举数的方法,该枚举数产生正方形数字

As an example, let's say I have a method that returns an enumerator which yields square numbers:

def square_numbers
  return enum_for(__method__) unless block_given?

  n = d = 1
  loop do
     yield n
     d += 2
     n += d
   end
end

square_numbers.take(10)
#=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

我想枚举前5个平方数,并为每个值打印随后的3个平方数。与 each_cons 无关紧要的东西:

And I want to enumerate the first 5 square numbers, and for each value, print the subsequent 3 square numbers. Something that's trivial with each_cons:

square_numbers.take(8).each_cons(4) do |a, *rest|
  printf("%2d: %2d %2d %2d\n", a, *rest)
end

输出:

 1:  4  9 16
 4:  9 16 25
 9: 16 25 36
16: 25 36 49
25: 36 49 64

我想通过两个嵌套循环以及 next clone 使用外部迭代: / p>

But unlike the above, I want to use external iteration using two nested loops along with next and clone:

outer_enum = square_numbers
5.times do
  i = outer_enum.next
  printf('%2d:', i)

  inner_enum = outer_enum.clone
  3.times do
    j = inner_enum.next
    printf(' %2d', j)
  end
  print("\n")
end

不幸的是,上述尝试 clone 引发:

Unfortunately, the above attempt to clone raises a:

`initialize_copy': can't copy execution context (TypeError)

我知道Ruby没有提供现成的功能。但是我如何自己实施呢?如何创建支持克隆 Enumerator

I understand that Ruby doesn't provide this out-of-the-box. But how can I implement it myself? How can I create an Enumerator that supports clone?

假设,这是实现 initialize_copy 并复制 n 和<$的两个变量值的问题c $ c> d ,但我不知道怎么做或在哪里做。

I assume that it's a matter of implementing initialize_copy and copying the two variable values for n and d, but I don't know how or where to do it.

推荐答案

无法复制Ruby光纤,并且Enumerator的C实现存储指向光纤的指针,该指针似乎不会以任何方式暴露给Ruby代码。

Ruby fibers cannot be copied, and the C implementation of Enumerator stores a pointer to a fiber which does not appear to be exposed to Ruby code in any way.

https://github.com/ruby/ruby/blob/752041ca11c7e08dd14b8efe063df06114a60。 / a>

https://github.com/ruby/ruby/blob/752041ca11c7e08dd14b8efe063df06114a9660f/enumerator.c#L505

if (ptr0->fib) {
    /* Fibers cannot be copied */
    rb_raise(rb_eTypeError, "can't copy execution context");
}

通过C源代码,显然枚举器和光纤之间的连接非常深刻。因此,我怀疑是否有任何方法可以更改 initialize_copy 的行为以允许 clone

Looking through the C source, it's apparent that Enumerators and Fibers are connected in a pretty profound way. So I doubt that there is any way to change the behavior of initialize_copy to permit clone.

这篇关于如何为外部迭代创建“克隆”功能的枚举器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆