- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
枚举器链的情况我无法理解:
[1, 2, 3, 4, 5].find.map { |x| x * x }
#=> [1, 4, 9, 16, 25]
这将返回初始值方 block 数组,但我希望它只返回 [1]
我试图解构所有内容,这就是我取得的成果:.map
在 find
枚举器上调用,用于原始数组。它调用自身的 each
来获取迭代值。枚举器上的 each
将迭代委托(delegate)给为其创建枚举器的方法,即 find
。 find
获取数组的第一个元素,让出它,并一直让出它,直到它到达示例中的 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/
我是一名优秀的程序员,十分优秀!