このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

REPL方式のWeb処理

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 |
// Print
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 |
// Print
send-response;
// Loop
repeat
}

Webリクエスト処理を無限に続けるweb-serverコマンドは次のように書けます*2


command web-server :: void -> never {
begin {
receive-request |
process-request |
send-response;
repeat
}
};

要するに、「読み取って、処理して、書きだす」の繰り返し。コンソールもWebも同じですね。

*1:現状のCatyでは、このコマンドを実装するのはちょっと面倒そうです。

*2:コマンド定義の本体ブロックはbeginブロックと解釈するので、内部のbeginブロックは省略してもかまいません。