Ruby 枚举器';s循环魔法(同时无中断和无终止循环)

Ruby 枚举器';s循环魔法(同时无中断和无终止循环),ruby,enumerator,Ruby,Enumerator,如何在枚举器内循环。new知道在何处停止 现在是更具描述性的例子。下面是两段代码,它们都返回相同的数组:[1,2,4,8]。但在第一个示例中,当第二个示例不知何故停止时,循环中的中断条件存在 示例#1带有break def simple n x = [] a = 1 i = 0 loop do x << a a *= 2 i += 1 break unless i < n # in this case condition for

如何在枚举器内循环。new知道在何处停止

现在是更具描述性的例子。下面是两段代码,它们都返回相同的数组:
[1,2,4,8]
。但在第一个示例中,当第二个示例不知何故停止时,
循环中的
中断
条件存在

示例#1带有
break

def simple n
  x  = []
  a = 1
  i = 0
  loop do
    x << a
    a *= 2
    i += 1
    break unless i < n # in this case condition for stop used
  end
  x
end
p simple(4)== [1,2,4,8]
def简单n
x=[]
a=1
i=0
环道

x考虑以下几点:

enum = Enumerator.new do |x|
  x << "hello"
  x << "world"
end

enum.take(1)
 #=> ["hello"]
enum.take(100)
 #=> ["hello", "world"]
由于您在可枚举项上调用了
take(4)
,因此
枚举器::Yielder
将知道如果已收集
4
项,将立即返回

…另一方面,如果您尝试运行例如
enumer.to_a
,则循环将一直持续下去,因为它没有任何提前退出的条件

从我发现的情况来看,关于这个如何工作的ruby文档有点少;但有:

/*
*电话号码:
*枚举器。新的(大小=零){| yielder |…}
*Enumerator.new(obj,方法=:each,*args)
*
*创建新的枚举数对象,该对象可用作
*可枚举的。
*
*在第一种形式中,迭代由给定的块定义,如
*哪个“yielder”对象(作为块参数给定)可用于
*通过调用+yield+方法(别名为所有类的+array)生成一个值
*
*/

感谢您的回答,它的信息量大且清晰。
enum = Enumerator.new do |x|
  x << "hello"
  x << "world"
end

enum.take(1)
 #=> ["hello"]
enum.take(100)
 #=> ["hello", "world"]
loop do
  x << a
  a *= 2
end
/*
 * call-seq:
 *   Enumerator.new(size = nil) { |yielder| ... }
 *   Enumerator.new(obj, method = :each, *args)
 *
 * Creates a new Enumerator object, which can be used as an
 * Enumerable.
 *
 * In the first form, iteration is defined by the given block, in
 * which a "yielder" object, given as block parameter, can be used to
 * yield a value by calling the +yield+ method (aliased as +<<+):
 *
 *   fib = Enumerator.new do |y|
 *     a = b = 1
 *     loop do
 *       y << a
 *       a, b = b, a + b
 *     end
 *   end
 *
 *   p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
 *
 * The optional parameter can be used to specify how to calculate the size
 * in a lazy fashion (see Enumerator#size). It can either be a value or
 * a callable object.
 *
 * In the second, deprecated, form, a generated Enumerator iterates over the
 * given object using the given method with the given arguments passed.
 *
 * Use of this form is discouraged.  Use Kernel#enum_for or Kernel#to_enum
 * instead.
 *
 *   e = Enumerator.new(ObjectSpace, :each_object)
 *       #-> ObjectSpace.enum_for(:each_object)
 *
 *   e.select { |obj| obj.is_a?(Class) }  #=> array of all classes
 *
 */