【Linq】LinqがPull型の特性を生かしきれていない理由

Linqは非常に有力な考え方として世界に普及しましたが、ReactiveExtensionが普及した今考えると、非常に"もったいない"考え方であると私は思う。

理由を語るためにLinq(Pull型)とRx(Push型)のフローを可視化してみる。

f:id:mkdyuzuki:20160615020626p:plain

これで分かるようにMoveNext命令は連続して実行する際は無駄であり、Rxに完全に置換できるのである。

ここでPull型が非効率的であると言っているわけでないことに留意していただきたい。

Pull型のPush型にない長所としては、

  • 次の値を取得する時期をカスタムできる
  • 取得命令のカスタマイズができる

これらの特徴を生かし、Linqの実装をサポートするのならば、

int GetCount()

void Move(int index)

T GetValue()

 

とすれば、今までのようなLinqの機能は包括され、Take()やSkip()などのインデックス操作は非常に高速化され、今まで出来なかった並べ替え操作も高速に実装できる。

不安要素としては初めにGetCount命令をするため、Countを保持しないデータ構造では

非効率になる場合があることだ。しかしCountを保持しとけばよい事である.。保持できないデータ型としてはLinkedListがあるが、LinkedListの操作はその他のコレクション型と大きな差異があり、それは例外的に処理することが望ましいだろう。

インデックスアクセスできないデータ型では非効率的になると思われるだろうが、二分木構造ではlog(N)で取得できるし、相対インデックスの絶対値が小さいならMoveNextのような処理を分岐すればよいのである。