読者です 読者をやめる 読者になる 読者になる

Iteratorって難しい……。

適当に書いたらカオス。


昔、Iteratorにすごく苦手意識があった。
C++だと、Iteratorを使った場合、

for (list<Hoge>::iterator it = hoges.begin(); it != hoge.end(); ++it) {
    (*it)->hogehoge();
}

などと書かなければならない。(もちろん簡略した形もあるけど)
これがいかにも「小難しい」と感じるのは僕だけではないと思う。

特にCから入った人間にとって、

for (Hoge* hoge = hogeListHead; hoge ; hoge = hoge->next ) {
    hoge->hogehoge();
}

と比べてもどうも違和感がある。
しかも、C++Iteratorは標準では素直にそのiteratorが指し示すnextやprevの操作を行えない。(ように見える)*1
最初は++とか--や*がなぜリストとその要素を操作する事になるのか直感的に分かりづらい、ということもある。

それに比べて、

for (Iterator<String> j = list.iterator();j.hasNext();) {  
    buffer.append(j.next());
}

などとと書けるJavaはやさすいぃ。


で、まぁ、本題として、


こう書き記しはしたけども、
言いたいことは
複数のリストに属する要素をIteratorで表すのって難しいよなぁ、とか。


所謂listAに属しつつlistBにも属する要素Eがあるとする。
そのEを順に走査するような処理があるとして、
listAの探索中に見つけた要素Eに対するlistBの次の要素がほすぃ、ということもある。


こういうとき、
おのおのの要素自体がiteratorを保持しておく、ということもできるんだけれども、
何となく泥臭いなぁ、と思ってしまうのであった。
要するに、

for (tag = (Tag*)tags.head(); tag ; tag = tag->next();) {
    if (tag->value == value) {
        if (tag->hasIndexPrev()) {
            ... // もう一つのリストの前の要素に対する操作
        }
        if (tag->hasIndexNext()) {
           ... // もう一つのリストの次の要素に対する操作
        }
    }
}

と書きたいときに、面倒だなぁと。
Cなら只のポインタの連結リストに過ぎないので、
それらが多重になっていても、割とflatに感じるのだが、
これをイテレータで示そうとすると随分面倒だ。


元々、自己言及的なprevやnextポインタを廃するためにlistなどを用いているのに、
結局的に自己を指し示すiteratorの管理に追われなければならないのだから支離滅裂な気さえする。


多重リストなんて、どれくらい使うのかわからんけど、
VRAMの動的管理などに使っていたので、ちょっと躊躇した憶えがある。


ということで、イテレータって難しいのう、と思ったのであった。

*1:現在のイテレータを保持したまま、前方、後方を指すイテレータが欲しいときはboostのnext,priorなどを使うと良いです