gpt4 book ai didi

ruby - 以 find 开头的枚举器链

转载 作者:太空宇宙 更新时间:2023-11-03 16:43:10 27 4
gpt4 key购买 nike

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

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

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

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

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

UPD

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

[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在 block 处理第一个值后不终止迭代,是collect_i collect 内的迭代器又名 map Enumerable 模块的方法显式返回 nil在每次迭代之后,无论调用 map 的 block 的返回值是多少或 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 安装,但是当我有机会时我会检查这个并用结果更新这篇文章。

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

关于ruby - 以 find 开头的枚举器链,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40239322/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com