- 2009-05-22 (金)
- 技術
継続と言うとSchemeが有名ですが、Rhinoのドキュメントを読んでいたら「Rhino 1.6R1」から継続が存在してたみたいだったのでとりあえず試してみた。
Rhino 1.6R1 変更ログ
継続とは?
継続と聞くとちょっと小難しいので、まずは軽く説明してみます。
継続とは「ある時点での状態」を変数に格納しておき、そのポイントに後から戻るということが可能になる概念である。
・・・
まったくもって小難しいのでとりあえず以下のSchemeのコードを見ていただきたい。
継続サンプル - Scheme
結果
こぶた
たぬき
きつね
ねこ
[via]
Schemeを作ろう 第3回
このコードではdisplayで文字を出力しているのだが、途中のcall/ccという部分が継続オブジェクトを生成している部分になる。
この継続オブジェクトをx変数にセットしているので、もし後でx変数に入っている継続オブジェクトを実行するとさらに
きつね
ねこ
と文字列が出力される。
このようにあるポイントを変数に記憶させておき後から呼び出せるのが継続になるのだ。
そしてそのときのスコープ内の値も保持されているのでクロージャっぽいですね。
ってかクロージャも継続と言ってもいいのかな?
Rhinoをインストールする
一応Rhinoを使ってJavaScriptの継続を試すのでのインストールを書いておきます。参考までに。
あとボクの環境がMacなのでWindowsの方は適宜読み替えていただきたい。
まずは以下からダウンロードします。
Rhino のダウンロード
そしてRhino Shellが使えるように、環境変数を設定しましょう!
ホールディレクトリにある.bash_profileファイルに以下を追記します。
(CLASSPATHに入れるパスはご自分の環境に合わせてくださいね。)
export CLASSPATH=/code/java/rhino1_7R1/js.jar
alias rhino="java org.mozilla.javascript.tools.shell.Main"
.bash_profileへの追記などは以下を参考にしてみてください。
Mac OS Xで環境変数にPATHを追加する方法
設定が終わったら、ターミナルから
$ rhino
と打つとそのままJavaScriptがirb形式でコードを入力できます。
rhinoから抜けたい場合は「quit()」と入力してください。
継続オブジェクトContinuationを使ってみよう
Rhinoで継続を使う場合は、Continuationというクラスをnewすることから始まります。
Continuationクラスをnewして変数に格納すれば、そこが継続として後から戻るポイントになります。
では実際に使ってみましょう!
このコードを保存してrhinoコマンドで実行します。
$ rhino -opt -1 -f coroutine.js
-opt -1は継続を使う場合に必要で、-fはファイルから実行するという意味になります。
Rhino Shell - MDC
先ほどのSchemeのコードに近い感じですが、showMessage関数を呼ぶとprint関数で順番に文字を出力していきますが、
途中にあるcall_cc関数内でContinuationクラスをnewして継続オブジェクトを返しています。
(ここでreturnされるオブジェクトはfunction型になります。)
そしてshowMessage関数の呼び出しの後に継続オブジェクトを関数として呼び出しています。
ただし継続オブジェクトが実行した後はc変数に入っている継続オブジェクトはundefinedになってしまうので、instanceofで継続オブジェクトかどうか判断しています。
これについては順番に説明して理解してみましょう!
以下にshowMessage関数を呼び出したところから処理の流れを記載してみました。
showMessage関数の呼び出し
↓
文字列の出力(hoge1)
↓
Continuationオブジェクトの生成
↓
文字列の出力(hoge2、hoge3)
↓
instanceofで確認→OK
↓
継続関数オブジェクトの実行
↓
文字列の出力(hoge2、hoge3)
↓
instanceofで確認→NG
↓
よって2回目の継続関数オブジェクトは実行されない
ちょっとややこしいですが、c()で継続関数を実行すると継続ポイントに戻って再度コードを実行していきますが、
再びc()の部分まで実行しようとしているのでそれをinstanceofで阻止している感じです。
また継続オブジェクトには引数を渡すこともできます。
「c("foo");」という感じで呼び出すと、「c = "foo"」と同じになり継続オブジェクトに渡す引数で処理を分岐したりもできます。
JavaScript1.7のyieldに似てる
一見yieldを使うと同じような雰囲気は出てるんですが、継続と少し違うのはyieldはポイントポイントで完全に処理が止まって待っててくれるのですが、
継続は処理をすべて1度実行しちゃいます。
継続とyieldの出力結果を見るとよく理解できると思います。
継続の場合の出力結果
hoge1
hoge2
hoge3
hoge4 ←ここが継続ポイント
hoge5
yieldの場合の出力結果
hoge1
hoge2
hoge3
まとめ
継続をどのようにうまく使うかなど、まだ全然理解できていないのでこれから少し掘り下げて勉強してみたいと思います。
(それならScheme勉強したほうが良さそうですねw)
あとGemmaさんの記事で、サーバーサイドJavaScript(Rhino)の継続でCoroutineを書いてみた - Gemmaの日記
というのがすごく参考になります、2つの関数を交互に実行する協調的マルチタスクな処理実装されています。
すごいっす。
Comments:0
Trackback:0
- TrackBack URL for this entry
- http://hisasann.com/cgi-bin/mt/mt-tb.cgi/1190
- Listed below are links to weblogs that reference
- RhinoでJavascriptの継続を使ってみる from HouseTect, JavaScript Blog


