kahua.partcont

English page

Kahua Release

kahua-web Release

Security Advisory

Event Log

Documentation

For developers

Site info

Related Site

[module] kahua.partcont

部分継続(partial continuation)を実装するモジュールです。

部分継続は、アプリケーションサーバの中でcall/ccのように暗黙の継続を捕捉 したい場合に役立ちます。例えば、

  • 深い再帰の途中でそれまでの結果をユーザに見せたい
  • 長い計算を一度中断してユーザに継続するかどうかを問い合わせたい

といったような場合です。

ここで、残念ながらcall/ccを直接使うことはできません。アプリケーションサー バ内でcall/ccを使って捕捉した継続は、その将来の計算全てを含みます。すな わち、「call/ccから戻って、ページを組み立てて、そのページを現在クライア ントとつながっているポートへと送り出す」ということです。

仮に、残りの計算をこのような継続に包み込んだ上で、現在までの途中結果を ページに組んでユーザに見せたとしましょう。そのページはクライアントとつ ながっているポートを通じて、クライアントへと送られ、ユーザの手元に表示 されます。

ユーザがその計算の続きを要求すれば、その要求はhttpに乗ってkahuaサーバへ と送られ、そこで先程捕捉しておいた継続が再開されます。捕捉されていた残 りの計算が行われ、ページが組み立てられて、そのページがポートを通じて... ちょっと待って。この継続から参照されているポートは、先程のリクエストに 対してリプライを返すためのポートです。既にそのリプライは終わっており、 ポートは閉じられているのです。ユーザは新たに接続したポートで残りページ を待っています。先程捕捉した継続は、その「新たなポート」のことを知りま せん。

これは、call/ccが、その時点から全ての未来の計算を捕捉してしまうために起 こる問題です。kahuaサーバの計算過程にとっては、ユーザへのリクエストとリ プライという部分はいわば「縁の下」の話であって、つかまえたい継続という のは「計算の続きをやって、ページを作る」ところまででいいのです。

部分継続を使うことで、この問題は素直に記述できます。

部分継続には、二つのプリミティブがあります。

[macro] reset/pc expr

このマクロは、部分継続の「出発点」をマークするプリミティブです。継続を マークした後に、式exprを評価します。

「継続をマークする」ということが何を意味するかは今は置いておい て、exprの評価が進んで結果が返って来た時の制御の流れをイメージして 下さい。2つの制御ポイントに注目します。

  1. exprから、制御が戻って来て、reset/pcがそれを受け取る
  2. reset/pcが、自身を呼び出した式へと制御を返す

expr中に、以下に述べるcall/pcプリミティブが無かった場合、この制御は 素直に流れます。すなわち、exprからの戻り値をreset/pcが受け取り、そ れをそのまま呼び出した式へと渡します。

[procedure] call/pc proc

直前のreset/pcまでの部分継続kを作成し、それを引数としてprocを呼 び出します。procの継続は直前のreset/pcの継続になります。

...と書いてもイメージが湧かないので、もうすこし具体的に説明してみましょう。 procは1引数の手続きなので、直接procをlambdaで書けばこんなふうに なります。

  (call/pc (lambda (k) body ...))
  1. body ... を素直に実行して最後まで到達したら、この式はreset/pcから 返る(reset/pcの第2の制御点にlongjmpする、という感じです)
  2. 部分継続 k を呼び出すと、それはcall/pcから返ります。そのあと計算 を続行して、reset/pcの第1の制御点、つまりexprからreset/pcに戻るとこ ろで、kの呼び出しから戻って来ます。

通常はkbody内で末尾呼び出しにしておいて、kから戻ったとこ ろでreset/pcから戻るようにしておきます。

ポイントは、reset/pc以降の計算の継続と、kからreset/pcまでの継続が切 り離されていることです。

kahua.serverモジュールは、アプリケーションサーバからアプリケーショ ンコードを呼び出す直前にreset/pcで継続をマークしています。したがって、 アプリケーションコードの中では、call/ccを使うかわりにcall/pcを使って、 アプリケーションロジック内で閉じた継続を捕まえることができます。クライ アントとの接続やデータベースとの接続といったものはreset/pcの外側で行わ れるため、call/pcで捕捉した継続の中には含まれません。

部分継続の使用例としては、Kahuaディストリビューション中にある examples/nqueen/ 等を参照して下さい。

[macro] let/pc k body ...

 (call/pc (lambda (k) body ...))

の簡略版です。


なお、このモジュールの実装は、下の論文を参考にしています。

Martin Gasbichler and Michael Sperber: Final Shift for Call/cc: Direct Implementation of Shift and Reset, ICFP 02, October 2002. http://citeseer.ist.psu.edu/gasbichler02final.html

この論文では、基本的なオペレータはreset, shiftと呼ばれています。 基本的に

  (reset expr) == (reset/pc expr)
  (shift k expr) == (call/pc (lambda (k) expr))

ですが、reset/pc, call/pcは多値も扱えます。

Copyright (c) 2003-2007 Kahua Project Contact | About Us