【问题标题】:Enumerator chain starting with find以 find 开头的枚举数链
【发布时间】:2016-10-25 11:56:41
【问题描述】:

有一个枚举器链的情况我无法理解:

[1, 2, 3, 4, 5].find.map { |x| x * x }
#=> [1, 4, 9, 16, 25]

这将返回初始值平方的数组,但我希望它只返回 [1]

我试图解构一切,这就是我所取得的成果:.map 在原始数组的 find 枚举器上被调用。它自己调用each 来获取迭代值。枚举器上的each 将迭代委托给为其创建枚举器的方法,即find。 find 获取数组的第一个元素,将其让出,并一直让出,直到到达示例中的块。该值被平方,块返回它,map 定义中的底层 each 块返回 [1],它下降到 find,并且由于它在布尔意义上是 true,我希望 find此时返回,有效地结束迭代,但不知何故,它一直将数组中的值一直提供到 map 块。

这不是一个真实的例子,我只是想了解如何正确读取这些链,这个案例让我感到困惑。

UPD

由于多次建议 find 在没有块的情况下调用会返回“默认”枚举器,因此这里有一个示例:

[1, 2, 3, 4, 5].find
#=> #<Enumerator: [1, 2, 3, 4, 5]:find>

[1, 2, 3, 4, 5].find.each { |x| x < 4 }
#=> 1

【问题讨论】:

  • 在没有块的情况下调用find没有多大意义,它返回default EACH_ENUMERATOR(点击“显示源”。)
  • 吹毛求疵,但 find 将返回单个元素 (1),而不是数组 ([1])。
  • @mudasobwa [1,2,3,4,5].find 返回#&lt;Enumerator: [1, 2, 3, 4, 5]:find&gt;,而源代码中只有RETURN_ENUMERATOR。也许我没有寻找正确的方向?但是,是的,这没有任何意义,这只是一个综合示例来说明一些奇怪的行为。
  • @Stefan map 是指示整个语句将返回什么的方法,如果我理解一切正确的话。但是find 在内部只会返回 1,是的。
  • @SergioTulentsev 我试图在此声明中掌握整个数据流。所以在我看来,collect 是在 #&lt;Enumerator: [1, 2, 3, 4, 5]:find&gt; 上调用的,它自己调用 each,它委托给原始数组上的 find。

标签: ruby


【解决方案1】:

好吧,我终于想通了。

find 在第一个值被块处理后没有终止迭代的原因是 collect_i 中的迭代器 collect aka map Enumerable 模块的方法在每次迭代后显式返回nil,没有不管通过调用map 或collect 提供的块的返回值是多少。这是,取自enum.c:

static VALUE
collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
{
    rb_ary_push(ary, enum_yield(argc, argv));

    return Qnil;
}

因此,在初始数组上对find 的内部调用总是得到nil 作为产生值的结果,因此在处理完最后一个元素之前不会停止迭代。这很容易通过将 ruby​​ 下载为存档并像这样修改此函数来证明:

static VALUE
collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
{
    rb_ary_push(ary, enum_yield(argc, argv));

    return ary;
}

从修改后的源代码保存并构建 ruby​​ 后,我们得到:

irb(main):001:0> [1,2,3,4,5].find.map { |x| x*x } => [1]

另一个有趣的事情是,Rubinius 完全像这样实现collect,所以我认为 MRI 和 Rubinius 有可能对这个语句产生不同的结果。我现在没有安装可用的 Rubinius,但是当我有机会时我会检查这个并用结果更新这篇文章。

不确定这是否会对任何人有用,除了可能是为了满足一个人的好奇心,但仍然:)

【讨论】:

    猜你喜欢
    • 2011-11-07
    • 2010-09-28
    • 1970-01-01
    • 2018-10-25
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多