🍣
[Feature #21520] Enumerator::Lazy で捜査している途中に出力を挟めるようにしたい提案
[Feature #21520] Feature Proposal: Enumerator::Lazy#lazy_each
-
Enumerator::Lazyを利用しているときに以下のように中間の要素を検証したい場合がある - 現状ではこれを行いたい場合に本来の用途ではない
#mapなどを利用する必要がある
(1..).lazy.map { |x| puts x; x }.select(&:even?).first(3)
- このようなケースで単に
eachを行うだけのEnumerator::Lazy#lazy_eachを追加する提案- イテレーションは行うが戻り値は通常の
#eachと同様にレシーバを返すだけ
- イテレーションは行うが戻り値は通常の
(1..).lazy
.lazy_each { |x| puts "saw: #{x}" }
.select(&:even?)
.first(3)
- これ、単に
#eachするだけだとだめなのかな?と最初思っていたんですが#eachしちゃうと『その時点でイテレーションが評価されてしまう』ので遅延処理には対応できないんですね
# each した時点で評価されるのでこのコードでは無限ループしてしまう
(1..).lazy.each { |x| puts x }.select(&:even?).first(3)
- 元々は
#peekって名前で提案されていたんですがフィードバックを受けて#lazy_eachという名前に変わりました-
Enumerator#peekという名前が既に存在しているがそっちと挙動が違うので- こっちは単に「次の」要素を返すだけ
- Enumerator#peek (Ruby 3.4 リファレンスマニュアル)
-
- 個人的にはあったほうが便利そうと思いつつデバッグ以外での用途があんまり思い浮かばなかったのでそれであれば元のコードでもまあ〜
-
lazy自体そこまで使いこなせてはいないんですが実際に実用的な場面ってあたりするんですかねー
Discussion