加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 如何使我的枚举器接口接受Feed?

发布时间:2020-12-17 04:17:12 所属栏目:百科 来源:网络整理
导读:从 docs for Ruby v2.5 e = [1,2,3].mapp e.next #= 1e.feed "a"p e.next #= 2e.feed "b"p e.next #= 3e.feed "c"begin e.nextrescue StopIteration p $!.result #= ["a","b","c"]end 但是当我通过Enumerator.new创建枚举时呢? # a naive rework of the abo
从 docs for Ruby v2.5
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创建枚举时呢?

# a naive rework of the above enum
e2 = Enumerator.new do |y|
  [1,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

我如何修改它以匹配API?

我尝试过的事情:

e2 = Enumerator.new do |y|
  [1,3].each do |x|
    @fed = yield
    y << x
  end
  raise StopIteration,@fed
end

e2 = Enumerator.new do |y|
  [1,3].each do |x|
    y << yield(x)
  end
  raise StopIteration,y
end

e2 = Enumerator.new do |y|
  enum = [1,3].each{|x| yield x }.to_enum
  y << enum.next
  raise StopIteration,y
end

有趣的是,当第二次调用feed时,它们都会产生相同的错误:

# Ignoring all the other errors that jump up…
p e2.next           #=> 1
e2.feed "a"
# nil
p e2.next           #=> 2
e2.feed "b"

TypeError: feed value already set

TypeError:已设置的feed值意味着它正在某处收集值,我只是不知道如何访问它.

#feed的C源代码:

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;
}

所以feedvalue是我的目标.我已经使用Pry进入了该方法的操作,但找不到与feed或feedvalue相关的方法或变量. Rubinius makes this available explicitly(至少作为实例变量).

我很难过.

任何帮助或见解将不胜感激.

解决方法

你的第一个例子是枚举数,其yield方法为:map:
e = [1,3].map
=> #<Enumerator: [1,3]:map>

你的第二个例子是一个枚举器,其yield方法为:each.

e2 = Enumerator.new do |y|
  [1,FED # <= how to get `FED`?
end
=> #<Enumerator: #<Enumerator::Generator:0x007fa69b056b50>:each>

您应该使用to_enum或enum_for以及您选择的yield方法:

[1,3].to_enum(:map)
=> #<Enumerator: [1,3]:map>

以下方式使用:: new现在已弃用,因此我不建议使用它来支持提供相同功能的to_enum或enum_for:

Enumerator.new([1,3],:map)

摘要

总结一下,#map是第一个迭代器调用的方法,当它是called时,它的return values将决定结果的值.当像其他例子一样使用#each时,你的块(#feed)结束并不重要,因为它不会影响#each的返回值.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读