🍣

[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 という名前に変わりました
  • 個人的にはあったほうが便利そうと思いつつデバッグ以外での用途があんまり思い浮かばなかったのでそれであれば元のコードでもまあ〜
  • lazy 自体そこまで使いこなせてはいないんですが実際に実用的な場面ってあたりするんですかねー
GitHubで編集を提案

Discussion