もうすぐKahua 1.0がリリースされるらしい
要約:
- https://www.kahua.org/cgi-bin/kahua.fcgi/kahua-web/
- http://practical-scheme.net/wiliki/wiliki.cgi?cut-sea の、Kahuaのところ
- Kahua 1.0リリースされたら早速いじって遊ぶ。リリース待ち。
イーガンっぽい部分要約:
- HTTPのウェブサービスは、可能な限り、多世界解釈的なアクセス構造に耐えられる必要がある。
- そこら辺(多世界解釈的アクセス構造)を限界まで考えていくと、やっぱり「(部分)継続をファイルに保存する」機能が欲しい。
- 「(部分)継続をファイルに保存する」とか、その辺を考えると、「順列都市」のコピー人格の実行を連想。
- 継続をファイルに書き出す場合、継続内の外部(データストレージや入力その他)とのつながりを抽象化しておく必要がある(portよりも更に)。
- HaskellみたいなIO構造が必要?
ゲーマー用の要約:
- ANOSは継続。A.D.M.Sも継続。第三視点も継続。セーブ&ロードも継続。
最初に書いておくと、自分はあまりKahuaをまじめにいじってないので(いじったのはかなり昔)、書いている内容が正しいという保証は無し。
また、分かりにくい記述があちこちにある為、あとで文章を書き直した方がいい気がする。
Kahuaは、ぶっちゃけて言えば、次のようなCGIコード(schemer以外の人が読む事も考えて、疑似Cコードで書きます)を、
/* サンプルコード1 */ /* 掲示板っぽいCGIを想定。 * 最初のアクセスで、通常画面とpostフォームを表示し(default動作)、 * postフォームに記述して書き込むと * 「この内容で書き込んでいいですか?」画面が出て(confirm画面)、 * そこで確認ボタンが押されると * 実際にその内容をデータストレージに書き込むと同時に * 完了画面へとリダイレクトを行い(submit)、 * 完了画面を表示する(done画面)、 * という一連の動作を行う。 */ int main () { char *errormsg; CgiParams *params = get_cgiparams(); switch (params->cmd) { case done: /* 完了画面を表示するだけ */ print_done_html(params); break; case submit: /* post内容を検証する */ if (errormsg = is_invalid_posted_data(params)) { print_error_html(errormsg); break; } /* POSTされたデータをストレージに書き込む */ store_posted_data(params); /* doneへとリダイレクトさせるレスポンスを出力して返す */ print_http_location("http://.../hoge.cgi?cmd=done"); break; case confirm: /* post内容を検証する */ if (errormsg = is_invalid_posted_data(params)) { print_error_html(errormsg); break; } /* post内容を表示し、これでいいかどうかの確認画面を表示させる */ /* この確認画面には、「ok」「ng」ボタンがあり、 * 「ok」ボタンを押すとsubmitに進み、 * 「ng」ボタンを押すとdefaultに戻るものとする。 */ /* 「ok」ボタンには、hiddenでpostされた内容のコピーが含まれている。 */ print_confirm_html(params); break; default: /* 通常画面とpostフォームを表示するだけ */ print_default_html(params); break; } return 0; }
次のような感じに書けたらいいな、という発想を具現化したものだと言える。
/* サンプルコード2 */ int main () { char *errormsg; while (1) { /* 通常画面とpostフォームを表示し、postフォームの内容を受け取る */ PostedData *data = print_default_html(); /* post内容を検証する */ if (errormsg = is_invalid_posted_data(data)) { print_error_html(errormsg); continue; } /* post内容を表示し、これでいいかどうかの確認画面を表示させる */ /* この確認画面には、「ok」「ng」ボタンがあり、 * 「ok」ボタンを押すとsubmitに進み、 * 「ng」ボタンを押すとdefaultに戻るものとする。 */ PostedData *data2 = print_confirm_html(data); if (data2->confirm != "ok") { /* 確認画面で「ok」じゃない方が押されたので、最初に戻る */ continue; } /* (dataは、既に内容検証に通っているので、 * サンプル1とは違い、二重に検証する必要は無い。) * (サンプル1では、確認画面を経由した時点で、最初にpostされた * paramsは失われてしまっているが、このサンプル2では、 * まだ変数dataに保持されているので、参照が可能。) * (「サンプル1でも、paramsの内容は同じじゃねえの?」と思った人は * セキュリティ意識が甘い。確かに通常は同じだが。) */ /* POSTされたデータをストレージに書き込む(※副作用を伴う動作) */ store_posted_data(data); /* doneへと明示的にリダイレクトさせる * (副作用を伴う動作を、ブラウザの「戻る」「進む」で * 二重に実行してしまわないようにする為、これが必要になる) */ print_redirect_to_next(); /* 完了画面を表示するだけ */ print_done_html(); /* 最初に戻る */ } /* NOTREACHED */ }
(他にも補助的な機能が色々とあるが、一番メインになるのはこの部分だと思う。)
で、これを実現する為に、KahuaやKahuaと同様の機能を提供するフレームワーク(他にも何個かある)は、部分継続や、CPS変換やら、パラメータのセッションへの保存やら、色々とややっこしいテクニックが使われている。
大まかでいいなら、何も考えずに記述しても特に問題は無いが、きっちり隅から隅まで問題なく記述しようとすると、セッションの破棄タイミングや、副作用のタイミング等を考えないといけない為、通常のCGI作成とは違った部分で脳味噌を使う必要がある。
(とは言え、慣れの範疇に入ると思われるし、非Kahua的CGIでも副作用のタイミングは結局、考えなくてはいけない。考えていない人は無意識の内にそれを解決しているか、ただ単に職務怠慢なだけだ。)
ところで、ウェブブラウザには「別のページとして開く」「別のタブとして開く」という機能がついている。
これを利用してページを複製すると、「okを選んだ後のページ」と「ngを選んだ後のページ」を同時に見る事が可能となる。
また、この機能を使わなくても、ブラウザの「戻る」「進む」を使えばほぼ同等の事が可能となる。
これを、実際のコードと対応させて考えてみる事にする。
まず、先のサンプル1の方では、ページ単位でコードが分岐している為、「okを選んだ後のページ」も「ngを選んだ後のページ」も、普通に並列に存在している。実に当たり前だ。
しかし、サンプル2の方では、二番目のif文とその前のところ、「PostedData data2 = print_confirm_html(data);」「if (data2->confirm != "ok")」ここで、未来が分岐してしまう。
このサンプルコードでは「ng」を押された方の未来は最初に戻るだけだが、「ok」を押しても「ng」を押してもそれぞれ別の画面へと遷移していくコードは容易に書けるし、そのような場合でも問題なく動作するのか?
結論から行くと、Kahuaなら問題なく動作する。
(しかし、同様のフレームワークの中には、このように動作しない不完全なものもある。せめて「戻る」ぐらいは対応しといてほしい、某フレームワーク!)
これは、Kahuaが、セッション毎アクセス毎に「継続ポイント」を作成し、過去の継続ポイントを(充分古くなってもうアクセスが無いだろうと判断されるまでは)ずっと保持する事によって実現している。
そして、「ok」「ng」でそれぞれ分岐した両方で、新しい「継続ポイント」が生成され、別々の未来として独立に先に進む事になる。
(これ以上の詳しい原理は説明すると長くなるので省略。興味を持った人はKahuaのサイト等を見て自分で調べましょう。)
この「継続ポイント」は、要するにゲームの「セーブポイント」とほぼ同様に機能する。
つまり、「セーブ可能なポイント」イコール、サンプル2のprint_*()関数イコール、ウェブブラウザに何かが表示されるポイントイコール、「別のページ/タブで開く」「戻る」「進む」が選べるポイント、という事になる。
要するに、選択肢が出現する毎に毎回新しいファイルに自動セーブされているのと同じ感覚になる。
しかし、「継続ポイント」が「セーブ」とは違うのは、「継続ポイント」は所詮プロセス内の存在なので、プロセスが終了してしまうと失われてしまうし、ファイルに書き出す事が出来ない(クイックセーブ的存在?)。
この機能が個人的に、どうしても欲しい。
過去の履歴として、継続ポイントそのものをログファイル等に残せるようにできれば、ウェブアプリ世界は、初期状態からの完全な履歴を残す事が可能になる。
しかも、ウェブアプリ世界はその成り立ち故に多世界解釈なので、多世界解釈の(アクセスされた範囲のみでの)履歴となる。これはイーガン好きなら見てみたい世界だ。
しかし、素のschemeでは環境を握ってしまう部分が多い為、もう少し抽象化の度合いを進めないと(副作用の除去やVM化等?)実現できなさそうなのが残念だ。
とは言え、実際のウェブアプリでは、全てをログファイルに残す意味は薄そうではあるが。
ウェブアプリではなく、もっとイーガンっぽい用途の為に使う必要がある。継続のシリアライズは。
とにかく、そんなこんなでKahua 1.0がリリースされたら、またいじりはじめてみようと思っている。
他の人も、興味を持ったら、試してみませんか?
scheme/S式は初めの内は、見た目が異様に見えるかもしれませんが、構文自体は見ての通り、これ以上無いぐらいに簡潔なので、間違った記述をしてしまう事も他の言語より少ないと思います、自分は。
ただ、Kahuaは、常駐し、メモリを大量に消費するので、共用サーバには不向きですが。