K.Maebashi's BBS 投稿フォーム
ハンドル名
件名
Link
>http://kmaebashi.com/programmer/devlang/regexp.html >> Java流の、要素を取り出すだけで強制的にポインタを進めてしまう仕様は、 >> ちょっとどうかと思うんですがねえ。 > >同感です。マージとかやりにくそう。 > > >というわけでどちらか片方にするなら、GoFの方が良いな、と思ってたりするのですが、以下のような関数を用意すれば、GoF方式とJava方式の両方をあまり手間をかけずに作ることができます。(両方欲しい、という訳ではありませんが) > >function iterator_GoF(foreach_CPS) { > this = new_object(); > this.first = closure () { > this.isDone = closure () { return false; }; > foreach_CPS(closure (item, cont) { > this.currentItem = closure () { return item; }; > this.next = closure () { cont(null); }; > }, > closure (ret) { > this.isDone = closure () { return true; }; > }); > }; > this.first(); > return this; >} > >function iterator_Java(foreach_CPS) { > this = new_object(); > closure () { > this.hasNext = closure () { return true; }; > foreach_CPS(closure (item, cont) { > this.next = closure () { cont(null); return item; }; > }, > closure (ret) { > this.hasNext = closure () { return false; }; > }); > }(); > > return this; >} > >function foreach(foreach_CPS, proc) { # ついでに作った > foreach_CPS(closure (item, cont) { cont(proc(item)); }, closure (ret) {}); >} > ># foreach_CPSは CPS(continuation passing style, 継続渡し形式)で書かれたforeachです。 ># つhttp://www.shiro.dreamhost.com/scheme/docs/cont-j.html > >これらの関数に対し、コレクション側でforeach_CPSを用意して渡せば >それぞれの関数に対応したイテレータが返されます。 > >例えば以下のような2分木があったとすれば > >tr = {13,{5,{3,{},{}},{13,{12,{},{}},{}}},{16,{16,{15,{},{}},{}},{17,{},{}}}}; > >function foreachTree_CPS(tree) { > return closure (proc, fin) { > closure internalIterate(node, cont) { > if (node.size() == 0) { > cont(null); > } else { > internalIterate(node[1], > closure (ret) { > proc(node[0], > closure (ret) { > internalIterate(node[2], cont); > }); > }); > } > }(tree, fin); > }; >} > >という関数を1つ定義するだけで > >print("foreach:"); >foreach(foreachTree_CPS(tr), closure (item) { print(" " + item); }); >print("\n"); > >print("GoF :"); >for (i = iterator_GoF(foreachTree_CPS(tr)); !i.isDone(); i.next()) { > print(" " + i.currentItem()); >} >print("\n"); > >print("Java :"); >for (i = iterator_Java(foreachTree_CPS(tr)); i.hasNext();) { > print(" " + i.next()); >} >print("\n"); > >のように、3種類のイテレータが使えてまあ便利。 >でもシーケンシャルなコレクションだとそれほど嬉しくはありません。 >CPSではforやwhileがまともに使えないので、例えば配列用のforeach_CPSは > >function foreachArray_CPS(array) { > return closure (proc, fin) { > closure loop(index, cont) { > if (index == array.size()) { > cont(null); > } else { > proc(array[index], closure (ret) { loop(index + 1, cont); }); > } > }(0, fin); > }; >} > >なんてことになって、要素数が多いとforeachに渡したときにクラッシュするなあ、とか、初期値と変数が遠いなあ、とか。 >今の実装だと末尾再帰の最適化は物凄く大変そうですしね。 > ># でもこの形式のループは個人的にはむしろ欲しかったりします、crowbar ver.0.3.02にcall/ccを付けたので。ちなみに、この時点で末尾再帰の最適化はやりやすくなったのですが、CRB_Objectが増えたので先にGCを改造しなければならないのでした(どうでもいい報告)。 > >この手法は、 >・外部イテレータを直接作るのが難しくて >・ループによらないアクセスが簡単な >データ構造(木とか) *では* 役に立ちます。 ># ライブラリが簡単に書けます。というのはそれほど嬉しいことではない気がする
spamよけのため、ここに「ほげぴよ」と入力してください。
削除パスワード :
クリック!