pull or push / LINQ or Rx
partitionedはstd::partitionのlazy版です。
一瞬「すげー」と思ったんですが,よく読んでみたら,単に source sequence を二回列挙してるだけっぽくて残念*1.というかまあ二回列挙していいなら全然難しくありませんよね.C# で書いたとしたらこんな感じでしょーか.
static class Make { public static Tuple<IEnumerable<T>, IEnumerable<T>> Partition<T>( this IEnumerable<T> source, Func<T, bool> pred) { return new Tuple<IEnumerable<T>, IEnumerable<T>>( source.Where(pred), source.Where(x => !pred(x))); } }
『2007/4/2 - 当面C#と.NETな記録』のころからこの話をしているような気がしますが,source sequence を複数回列挙するような LINQ 演算子は邪道というのが私の持論です.
しかしながら source sequence の列挙回数は最大 1 回という条件を満たそうとすると,partition 系の分岐操作で面倒なことになります.このあたりは pull 型の連鎖である LINQ の宿命でしょうか.
以前『パイプライン色々: top down vs. bottom up (2) - NyaRuRuの日記』でまとめましたが,分岐操作は push スタイルの方が向いています.ちょうどタイミング良く .NET Reactive Framework (Rx) が最近ホットなので,興味がある人はチェックしてみると良いでしょう.Rx は push スタイルでイベントの連鎖を記述するため,partition 操作には向いているはずです.
参考
- Channel 9
- Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx)
- Kim Hamilton and Wes Dyer: Inside .NET Rx and IObservable/IObserver in the BCL (VS 2010)
- Erik Meijer and Wes Dyer - Reactive Framework (Rx) Under the Hood 1 of 2
- Erik Meijer and Wes Dyer - Reactive Framework (Rx) Under the Hood 2 of 2
- JVM Language Summit 2009 - Meijer on .NET Reactive Framework