【发布时间】:2017-04-24 21:19:41
【问题描述】:
我有一个惰性求值,我想要一个 map 操作产生的第一个真实结果,我又一次发现自己在我的表达式末尾写了 .find { |e| e }。
这是一个简单的例子;当然,数组和地图块在我的现实生活中是不同的:
[nil, 2, 3, 4].lazy.map{ |e| e }.find { |e| e }
当我必须将块 { |e| e } 添加到 select 或 find 时,我总是有点惊讶/失望,特别是如果它是一个懒惰的评估,因为两者 - 冗余 - 似乎都是身份函数默认:
> [nil, 2, 3, 4].find { |e| e }
=> 2
> [nil, 2, 3, 4].find
=> #<Enumerator: [nil, 2, 3, 4]:find>
> [nil, 2, 3, 4].find.map { |e| e }
=> [nil, 2, 3, 4]
这个枚举器与从.each 获得的枚举器实际上有什么不同吗?
> [nil, 2, 3, 4].each.map { |e| e }
=> [nil, 2, 3, 4]
与select 类似,但对惰性更无用:
> [nil, 2, 3, 4].select
=> #<Enumerator: [nil, 2, 3, 4]:select>
> [nil, 2, 3, 4].select { |e| e }
=> [2, 3, 4]
> [nil, 2, 3, 4].select.lazy.force # doing it wrong looks functional!
=> [nil, 2, 3, 4]
> [nil, 2, 3, 4].lazy.select { |e| e }.force
=> [2, 3, 4]
> [nil, 2, 3, 4].lazy.select.force # same without .force
ArgumentError: tried to call lazy select without a block
这些明显的身份(和ArgumentError!)是否有用,或者只是在未来版本的 Ruby 中提供更好默认值的机会?
【问题讨论】:
-
cycle没有块返回一个无限循环的枚举器(即next可以无限期地应用),所以与其他的略有不同。
标签: ruby default identity lazy-evaluation enumerable