lastValue
但是当我通过e = [1,2,3].map
p e.next #=> 1
e.feed "a"
p e.next #=> 2
e.feed "b"
p e.next #=> 3
e.feed "c"
begin
e.next
rescue StopIteration
p $!.result #=> ["a", "b", "c"]
end
创建枚举时呢?
Enumerator.new
如何修改此内容以匹配API?
我尝试过的事情:
# a naive rework of the above enum
e2 = Enumerator.new do |y|
[1,2,3].each do |x|
y << x
end
# raise StopIteration, FED # <= how to get `FED`?
end
p e2.next #=> 1
e2.feed "a"
p e2.next #=> 2
e2.feed "b"
p e2.next #=> 3
e2.feed "c"
begin
e2.next
rescue StopIteration
p $!.result #=> nil
end
有趣的是,当第二次调用e2 = Enumerator.new do |y|
[1,2,3].each do |x|
@fed = yield
y << x
end
raise StopIteration, @fed
end
e2 = Enumerator.new do |y|
[1,2,3].each do |x|
y << yield(x)
end
raise StopIteration, y
end
e2 = Enumerator.new do |y|
enum = [1,2,3].each{|x| yield x }.to_enum
y << enum.next
raise StopIteration, y
end
时,它们都会产生相同的错误:
feed
TypeError:已设置Feed值
TypeError:已设置的Feed值表示它正在收集值某处,我只是不知道如何访问它。
#feed的C源:
# Ignoring all the other errors that jump up…
p e2.next #=> 1
e2.feed "a"
# nil
p e2.next #=> 2
e2.feed "b"
所以static VALUE
enumerator_feed(VALUE obj, VALUE v)
{
struct enumerator *e = enumerator_ptr(obj);
if (e->feedvalue != Qundef) {
rb_raise(rb_eTypeError, "feed value already set");
}
e->feedvalue = v;
return Qnil;
}
是我的目标。我已经使用Pry进入了该方法的操作,但无法找到与feedvalue
或feed
相关的方法或变量。 Rubinius makes this available explicitly(至少作为实例变量)。
我很难过。
非常感谢任何帮助或见解。
答案 0 :(得分:3)
你的第一个例子以它的方式工作的原因是因为你使用#map“将数组的元素传递给”yield“并将”yield“的结果收集为数组。”在Enumerator#feed http://ruby-doc.org/core-2.5.0/Enumerator.html#method-i-feed
中有一个有趣的注释无论如何,如果您还在其上调用map
,您的自定义枚举器的行为方式与第一个示例中的数组相同:
e2 = Enumerator.new { |y|
[1,2,3].each do |x|
y << x
end
}.map
p e2.next #=> 1
e2.feed "a"
p e2.next #=> 2
e2.feed "b"
p e2.next #=> 3
e2.feed "c"
begin
e2.next
rescue StopIteration
p $!.result #=> ["a", "b", "c"]
end
答案 1 :(得分:1)
您的第一个示例是枚举数,其yield方法为:map
:
e = [1,2,3].map
=> #<Enumerator: [1, 2, 3]:map>
您的第二个示例是一个枚举数,其yield方法为:each
。
e2 = Enumerator.new do |y|
[1,2,3].each do |x|
y << x
end
# raise StopIteration, FED # <= how to get `FED`?
end
=> #<Enumerator: #<Enumerator::Generator:0x007fa69b056b50>:each>
您应该使用to_enum或enum_for和您选择的收益率方法:
[1,2,3].to_enum(:map)
=> #<Enumerator: [1, 2, 3]:map>
现在不推荐使用以下方式使用::new
,因此我 NOT 建议使用它,而不是to_enum
或enum_for
,它们提供相同的功能:
Enumerator.new([1,2,3], :map)
总结一下,#map
是第一个迭代器调用的方法,当它是called时,它的return values将决定结果的值。与其他示例一样使用#each
时,阻止阻止(#feed
)的内容并不重要,因为它不会影响#each
的返回值。