イテレータ

Pythonの、あるクラスに対するiterateは、例えば以下のように行う。


for i in A(1, 6):
print i, # => 1 2 3 4 5

つまり、イテレータのカーソルデータをインスタンスオブジェクトの中に埋め込む訳であり、クラスの中にイテレータを実装する訳である。これは、__iter__というフックメソッドを使用して実装する。


C++STLのように、イテレータ(処理)は、オブジェクト(データ)と別のものとして分けて考える場合もあるが、結局、イテレータの指すデータの型をイテレータから取り出せるように、各データ構造から、それ用のイテレータのファクトリを用意している。
イテレータの実装も各データ構造に依存して変わるので、結局、データ構造と分離するとこのようなアプローチとなる。Javaでも同様。


しかし、私の考えでは、これは静的型付け言語だと、あまり抽象化した方法で実装ができなくなる。
なぜなら、イテレータの指すデータの型の個数分だけ、イテレータのデータ型も用意しないといけないからだ。
例えば、以下のよう。


例えば、STLのstd::vectorを使用するとして、
Aを指すなら、std::vector<A>::iterator
A*を指すなら、std::vector<A*>::iterator
A*を指して、書き換えたくないなら、std::vector<A*>::const_iterator
Bを指すなら、std::vector<B>::iterator


結局、あるデータ構造があり、このデータ構造自体がシーケンスなデータ構造であれば、イテレータに関するデータ(カーソル)と処理をデータ構造自体に持たせてやれば、抽象的な実装ができそうである。
これは、結局、Pythonのアプローチであるが、C#ではどうなっているかは、まだ勉強してないので不明である。
しかし、例えば、forステートメントと結合するのであれば、言語的なサポートも必要である。
結局、クライアント側の実装がきれいになれば良いという考えもあるのだが、サプライヤ側(ライブラリ側)の実装もきれいにならない限り、汎用度は上がらないはずである。


また、Pythonでは、内包表記というのがあり、あるリストが欲しいなら以下のように書ける。


[x for x in range(1, 6)] # => [1, 2, 3, 4, 5]