CatyScript2.0の構文(まだ実装はありません)を使って、Caty自身のメカニズムを説明するのはなかなか具合がいいですね。なので、またCatyScriptを使ってCatyの説明をします。
Catyは当初から「対話的シェルとWeb処理を同じメカニズムにする」方針で設計・実装しています。これはどういうことか? CatyScriptで書かれた対話的シェルとCatyScriptで書かれたWebリクエスト処理を比べてみれば明らかになります。
まず、対話的シェルを再掲すると:
"Caty interactive shell" | cout; // オープニングバナー
/* トップレベル・ループ */
begin {
"> " | cout --no-nl; // プロンプト、改行しない
cin | eval | xjson:pretty | cout; // read-eval-print
repeat
}
バナー、プロンプト、プリティプリントを取り払うと、次のように単純化されます。
begin {
// コンソール(キーボード)から1行を入力
cin |
// 入力を式と解釈して評価
eval |
// コンソール(画面)に結果を出力
cout ;
// 繰り返し
repeat
}
このようなループを、Read-Eval-Print Loop、略してREPLと呼びます。すぐ上のスクリプトのコメントを書き直して、R・E・P・Lを明らかにすれば次のとおりです。
begin {
// Read
cin |
// Eval
eval |
cout ;
// Loop
repeat
}
Web処理もREPLなのですが、cin(console input)とcout(console outpu)に相当する“WebからのRead”と“WebへのWrite”を行うコマンドを準備しておきます*1。
/* Webから本物のリクエストを受け取る */
receive-request :: void -> WebRequest;/* Webに本物のレスポンスを送り出す */
send-response :: WebResponse -> void;
実際のリクエスト処理は、次のように定義されるprocess-requestコマンドで表現できるのでした(すぐ下に絵もあります)。
command process-request :: WebRequest -> WebResponse {
try {dispatch-request | exec | confirm-response} |
when {
#except => try {map-exceptions.caty | confirm-response} |
when {
#except => http-error-500,
#normal => pass
},
#normal => pass
}
};
以上のコマンド群を使ってWebアプリケーションサーバーの動作は次のように記述できます。
begin {
// Read
receive-request |
// Eval
process-request |
send-response;
// Loop
repeat
}
Webリクエスト処理を無限に続けるweb-serverコマンドは次のように書けます*2。
command web-server :: void -> never {
begin {
receive-request |
process-request |
send-response;
repeat
}
};
要するに、「読み取って、処理して、書きだす」の繰り返し。コンソールもWebも同じですね。