Kahua Release
- Release Note
- Download
- Current Version 1.0.7.3 (2008-05-08)
kahua-web Release
- kahua-webとは
- Release Note
- Download
- Current Version 0.3.1 (2007-06-12)
Security Advisory
Event Log
Documentation
For developers
Site info
Related Site
はじめての Kahua
以下は現状の Kahua の利用方法、Kahuaアプリケーションの作成方法の解説で すので変更する可能性があります。
本資料を読むときに必要なのは次のとおりです。
- Scheme のちょっとした知識(lambda とは、define とは何か、とか)
- Guache を動かすことのできる環境(Cygwin上では Kahua は動作しません)
- はじめての Kahua
インストール
詳細は Kahua パッケージに含まれている INSTALL ファイルを参照してください。 もしくは Setup をご覧下さい。
また、Kahua を利用するためには、pthreadをサポートした Gauche 0.8.7 以降が必要です。適宜、インストールしてください。
Kahua をインストールしよう
リリース版はDownloadからダウンロードできます。
$ ./configure --with-cgidir=[どっか]
最新版はCVS版になります。CVS から取ってきた場合は次のようにしてください。
$ ./DIST gen # CVS版のみ取ってきたときだけ $ ./configure --with-cgidir=[どっか]
この cgidir は、apache などで実行する CGI を配置できるディレクトリを指定 してください。そこに後述する kahua.cgi を置くことになります。
$ make $ make check # セルフテスト $ su # root になって $ make install $ exit # root じゃなくなって
ここで、kahua.conf を作ります。現状では /usr/local/etc/kahua/kahua.conf がデフォルト位置です。このファイルに次のように書いてください。
(make <kahua-config> :sockbase "unix:/usr/local/tmp/kahua" :working-directory "/usr/local/var/kahua" :static-document-path "/var/www/html/kahua" :static-document-url "/kahua" :auto-restart #t )
この設定では、
- /usr/local/var/kahua に作業用ディレクトリができます。
- 動的に生成されない静的なファイル、たとえばイメージなどは /var/www/html/kahua 以下に置くようになります。
- その静的なページへは、apache 経由でアクセスするときは /kahua/... になります。
ご自分の環境にあわせた設定を行ってください。
ちなみに私は自分のホームディレクトリ以下に作っております。この場合、パー ミッションにおいて楽をすることができます。つまり、後述する設定を省くこと ができます。試験用にはいいんじゃないでしょうか。
;; /home/ko1 がホームディレクトリだった場合、 (make <kahua-config> :sockbase "unix:/home/ko1/tmp/kahua" :working-directory "/home/ko1/kahua" :static-document-path "/home/ko1/kahua/static" :static-document-url "/static" )
詳細: kahua.config
その後、kahua.conf で設定した内容に従って、必要ならグループおよび権限 の設定をしてください。
$ chgrp -R [kahua] [KAHUA_WORKDIR] [KAHUA_SOCKBASE] [KAHUA_DOCDIR] $ chmod -R g+ws [KAHUA_WORKDIR] [KAHUA_SOCKBASE] [KAHUA_DOCDIR]
KAHUA_SOCKBASE: ソケットを作成するディレクトリ。デフォルトは/usr/local/tmp/kahua。 :sockbase で設定したディレクトリ。
KAHUA_WORKDIR: 作業ファイルディレクトリ。デフォルトは/usr/local/var/kahua。 :working-directory で設定したディレクトリ。
$KAHUA_DOCDIR 静的ドキュメントディレクトリ。デフォルトは/var/www/kahua。:static-document-path で設定したディレクトリ。
サンプルプログラムをインストールしよう
で、例をインストールします。
$ su [kahua の実行するためのユーザ] $ make install-examples [KAHUACONFIG="-c [kahua.conf の場所]"]
KAHUACONFIG="-c [kahua.conf の場所]" は、kahua.conf を /usr/local/etc/kahua/kahua.conf 以外に設定した場合に指定してください。
以下、kahua-* プログラムではこのオプションが必要になりますが、オプション "-c ..." の意味はこれと同じです。
動かしてみよう
$ kahua-spvr -i [KAHUACONFIG="-c [kahua.conf の場所]"]
を実行してみましょう。
"kahua> " というプロンプトが表示されましたね。
おめでとうございます!成功です!
-i を忘れると何も言ってくれませんので注意が必要です。デーモンとして動作 させるような、本番運用では -i オプションは必要なくなると思います。
アクセスしてみる
ウェブブラウザで kahua.cgi にアクセスしてみてください。
kahua.cgi を置いたところ(デフォルトでは /usr/lib/cgi-bin/ に置かれま す)に、ウェブサーバへアクセスします。デフォルトで http ://localhost/cgi-bin/kahua.cgi になる気がします。ウェブサーバの設定 に依存します。ご注意ください。
サンプルで遊んでみる
現在、 make install-examples を実行すると、次のようなサンプルアプリケ ーションがインストールされます。もちろん、すべて Kahua を用いて記述して あります。
- lambdabooks : オンライン本屋風サンプルアプリケーション
- wiki-iki : Kahua による Wiki の実装
- login : ユーザ管理用アプリケーション
- nqueen : Kahua の継続を利用して複雑な計算をインタラクションをとりながら進めていくアプリケーションをこれだけ短くかけました、というサンプル
- lazy-nqueen : nqueen を遅延評価を利用して実装したサンプル
- foldlist : ツリーを開いたり閉じたりする単純なサンプル
これらは、http ://.../kahua.cgi/lambdabooks などと kahua.cgi 以降にアプ リケーション名を追加してアクセスすることができます。
lambdabooks や wiki-iki は Kahua でこういうアプリケーションが作れるんだ、 ということを知ってもらうためのサンプルです。ですが、その分ちょっと大きい です。
foldlist などは、規模が非常に小さく、どうやって書くのかな、というのをち ょっとソースを見てみるか、というむきにはいいと思います。ソースは設定した [working-directory]以下の [working-directory]/checkout/foldlist/foldlist.kahua にあります。
kahua-web で遊んでみる
Kahua プロジェクトが送るキラーアプリケーション第一弾(多分)である kahua-web も、もちろんご利用いただけます。
インストールや使い方などの詳細はkahua-web をごらんください。
はじめての Kahua プログラム
サンプルを実行されましたでしょうか。あのようなウェブアプリケーションが Scheme で簡単に実現できるのが Kahua のすごいところです。
本項では、この Kahua プログラムを書くための基礎の基礎をご説明いたします。
Kahua の基本
Kahua アプリケーションの記述方法を説明する前に、まず Kahua の基本的な コンセプトを並べておきます。
Kahua はアプリケーションサーバを作るためのインフラストラクチャです。次 のような特徴があります。
- だいたい Scheme でかかれています。
- いくつかのアプリケーションサーバをいっぺんに起動したりします。
- アプリケーションサーバは *.kahua というファイルで記述します。
- *.kahua の実行はサンドボックス上で実行され、危ないことは出来ません。
- *.kahua の機能を拡張するため、プラグインを提供することができます。
- 継続ベースのウェブアプリケーションサーバが簡単に作れます。
- 標準で永続化データベースが簡単に使えます。
- クラスの再定義機構が利用できます。
- Emacs との連携で簡単に開発ができます。
- ほかにもいろんな機能があります。
ウェブサーバアプリケーション作成について言えば、次のような利点があります。
- 複数のインタラクションが必要なウェブページを一つの手続きで作成できます。
- CGI インターフェースによって面倒なことは一切必要ありません。
詳細: About Kahua Servers
ずらずらと並べましたが、全部ここで理解しないと進めない、というものでは ありませんので「こんなもんか」と思ってもらえれば結構です。これらの特徴に ついてはおいおいご説明していきます。
ファイル・ディレクトリ構成
Kahua の利用するディレクトリ、およびファイルの構成をまずはおさえておき ましょう。
kahua.conf で :working-directory というのを設定しましたが、これがKahua システムにおいて非常に重要なディレクトリになります。以下、ここで設定した ディレクトリを work-dir と呼びます。
work-dir 以下のファイル・ディレクトリ構成は次のようになっています。
$(working-directory)/app-servers ;; 重要
checkout/ ;; 重要
[その他]/ ;; 知らなくてもいいです。というか、私もよく知りません。
app-servers
詳細: kahua-spvr
このファイルにはどんなアプリケーションサーバを起動するかを書いておきま す。たとえば次のように記述します。
;;; app-servers の例 ( ;; (<type> :arguments (<arg> ...) :run-by-default <num>) ;; See http://www.kahua.org/cgi-bin/index.cgi/kahua-spvr (lambdabooks :arguments () :run-by-default 1) (wiki-iki :arguments () :run-by-default 1) (login :arguments () :run-by-default 1) )
この場合、lambdabooks、wiki-iki、login というアプリケーションサーバが 利用できるようになっています。
:run-by-default を 0 以外の数字に変更した場合、その数字だけそのアプリ ケーションサーバプロセスを起動します。ここは何も気にしないで 1 にしてお いてください。
checkout ディレクトリ
checkout ディレクトリ以下にはアプリケーションサーバごとに *.kahua を 配置します。
たとえば、アプリケーションサーバ hello を置くときには、 $(working-directory)/checkout/hello/hello.kahua が絶対に必要になります。アプリケーションサーバを起動するとき、これを起動します。
hello Kahua!
では、最初の Kahua プログラム、hello.kahua を作ってみましょう。
まず、設計しましょう。
アクセスされたら簡単のために次のような html が返るようにしましょうか。
<html>
<head>
<title> hello kahua! </title>
</head>
<body>
<h1> Hello Kahua! </h1>
</body>
</html>
とても簡単なサンプルであくびが出そうですが、こちらも考えるのが面倒なの でこういうのでお茶を濁すことにします。
では、$(working-directory)/checkout/hello/hello.kahua の作成を開始しましょう。
(define (hello-kahua)
(html/ (head/ (title/ "hello kahua!"))
(body/ (h1/ "Hello Kahua!"))))
(initialize-main-proc hello-kahua)
こんな感じでしょうか。ここでは細かいことは気にしないでおいてください。
hello を動かそう
まず、app-servers に hello アプリケーションを追加します。
;;; app-servers の例 ( ;; (<type> :arguments (<arg> ...) :run-by-default <num>) ;; See http://www.kahua.org/cgi-bin/index.cgi/kahua-spvr (lambdabooks :arguments () :run-by-default 1) (wiki-iki :arguments () :run-by-default 1) (login :arguments () :run-by-default 1) (hello :arguments () :run-by-default 1) ;; <<- 追加 )
そして、kahua-spvr を(もしまだ動いていれば)再起動してください。 kahua-spvr の終了は Control-C です。
では、ブラウザで http : //.../kahua.cgi/hello へアクセスしてみましょう。
<html><head><title>hello kahua!</title ></head ><body><h1>Hello Kahua!</h1 ></body ></html >
のような html が返ってくると思います。というか、今やったら返ってきました。 予想していたのとはインデントが違うような気がしますが、意味的には同じです ね。よかった、成功です。
おめでとうございます。あなたも立派な Kahua デベロッパーです。
hello の解説
hello.kahua に書いたものの意味がわからなくて気が狂いそうなあなたのため に、少し解説します。
initialize-main-proc は、このアプリケーションサーバに接続されたときに起 動する scheme の手続きです。ここで指定する手続きは HTML要素を返す手続き を返さないといけません。(本当は、html要素をあらわすシンボルの tree でも いいんですが)
って書いてもよくわかりませんね。私もわかりません。具体的には hello-kahua 手続きを見てみましょう。
再掲:
(define (hello-kahua)
(html/ (head/ (title/ "hello kahua!"))
(body/ (h1/ "Hello Kahua!"))))
html/ とか、見覚えがありますねぇ。多分、これが <html> </html>要素にな りそうです。他にも、(h1/ "Hello Kahua!") っていうのが <h1> Hello! Kahua! </H1>になりそうです。
これらの手続きは、html要素を返す手続きを生成して(本当はもう少し複雑) くれるそうです。簡単ですね。
これらを利用して HTML のページが記述できます。
もっと hello - エントリを追加しよう
さすがにこれだけだと石を投げられそうなので、もう少しリッチなアプリケー ションを考えてみましょう。
kahua.cgi/hello/world
とアクセスされたとき、別のアクションをするようにしてみましょう。
このような用途のためには、 define-entry を使います。
(define-entry (world)
(html/ (head/ (title/ "hello kahua! - world"))
(body/ (h1/ "Hello Kahua!")
(h2/ "Hello World!"))))
上記のスクリプトを、さっきの hello.kahua に追加してください。
これで、kahua.cgi/hello/world とアクセスすると、
<html><head><title>hello kahua! - world</title ></head ><body><h1>Hello Kahua!</h1 ><h2>Hello World!</h2 ></body ></html >
が返ってきます。
さて、html とか body とか、同じような要素があるから、ちょっと リファクタリングしましょう。
;; -*-scheme-*-
;; hello.kahua
(define (page ttl . elems)
(html/ (head/ (title/ ttl))
(body/ (node-set elems))))
(define (hello-kahua)
(page "hello kahua!" ;; title
(h1/ "Hello Kahua!")))
(define-entry (world)
(page "hello kahua! - world"
(h1/ "Hello Kahua!")
(h2/ "Hello World!")))
(initialize-main-proc hello-kahua)
こんな感じですかね。page という手続きで全体のページデザインをまとめて みました。簡単な Scheme プログラムですね。
node-set という関数が出てきましたが、(list (xxx/ ...) (yyy/ ...) ...) をまとめて一つの関数にするものです。リストが出てきたら使いましょう。
もっともっと hello - 継続を使ってみよう
継続ベースとか言ってるのに継続が出てこないじゃないか! と思った人のため に、そろそろ継続を使ったサンプルを書いてみましょう。
さて、kahua の継続は、「Scheme つったら call/cc だろう!」と思ってしま う人の call/cc で取得する継続と一対一で対応しません。えー、マジかよーっ て感じですが、まぁマジです。私も誤解してました。
では、何かというと「継続渡しスタイル(Continuation Passing Style)」 とかで言われる「継続」です。
参考: www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Scheme%3aCPS?
たとえば、
(define (adder/cps x y cont/proc) (cont/proc (+ x y))) (define (main) (adder/cps 1 2 display))
という定義があったとき、 (main) という式は何をやるか、を日本語で書いてみると、
mainさん: 「adder/cps さん、1 と 2 を渡すから、それを計算した
結果を display に渡してね」
adder/cpsさん: 「mainさんから 1 と 2 と display を受け取ったぞ、俺の仕事は 1 と 2 を足すことだから、その結果を display に渡そう。これで俺の仕事終わり」
display さん: 「3 を表示すんのね」
こんな感じになりましょうか。
たとえば、main さんが display じゃなくて、やっぱり改行したいから display の代わりに (lambda (arg) (display arg) (newline)) を渡しても正し く動きます。
また、adder/cps が、cont/proc を実行しないで、どこかに保存して返ってし まうこともできます。たとえば、
(define next #f) (define (adder/cps x y cont/proc) (set! next (lambda () (cont/proc (+ x y)))))
このようにすると、
(main) ;; undef (next) ;; -> 3 を表示
のようなことができます。
さて、ウェブアプリケーションで継続を扱えると何が嬉しいのでしょうか。
ウェブアプリケーションで考えると、HTTP自体がステートレスな通信なので、 基本的に 1リクエスト、レスポンスでやることを全部やらないといけません。 そのため、複雑なインタラクションをするようなアプリケーションの実装は困難 でした。たとえばセッションオブジェクトを利用して実装していましたが、セッ ション情報として「継続」の代わりになる情報をすべて保存しなければなりませ んでした。
そこで、Kahua では「継続」の保存と復帰を非常に扱いやすいものにしました。 つまり、サーバ側ではある処理を中断したとき「クライアントからこのアクショ ンがあったら続きとしてこれをやる」ということを簡単に登録できます。具体的 にクライアントのアクションとは何か、ということになるとたとえば「あるリン クをクリックする(あるページを要求する)」ことや「あるフォームを入力する」 ことにあたります。
では、具体的に何か作って見ましょう。
しかし、hello にどういう継続を入れますかねぇ。
リンクをクリックすると、数をどんどん増やすようなアプリケーションにして みましょうか。やっぱり実用性無さげですが。
そんなもん、session とかで情報を渡しても出来るわ!とか言われそうです が、まぁ簡単なサンプルってことで。
(define-entry (counter)
(define (viewer count)
(page "hello kahua! - counter"
(h1/ "Hello Kahua!")
(h2/ (format "count is ~a" count))
(p/
(a/cont/ (@@/ (cont
(lambda () (viewer (+ count 1)))))
"inc count") " , "
(a/cont/ (@@/ (cont
(lambda () (viewer (- count 1)))))
"dec count")
)))
(viewer 0))
こんな感じでしょうか。http : //.../kahua.cgi/hello/counter とアクセスす ることでこのページが表示されます。
a/cont/ というのは「このリンクをたどったとき、指定した継続を実行しろ」 とサーバに登録するためのものです。継続の指定は「(@@/ (cont proc))」 と指 定することで行います。
つまり、(a/cont/ (@@/ (cont proc)) "...") と記述すると、「"..." という リンクをたどると proc が実行」するような意味になります。
HTML ではリンクは <a href='dokka'> dokka </a> と書きますが、Kahua で (a/cont/ (@@/ (cont proc)) "dokka") と書くことで <a href=「proc を実行し てくれるリンク」> dokka </a> と出力されます。
ここで、proc が継続になるわけです。
次は、formの入力と、その入力を受取って実行するための継続を書いてみましょう。
数あて、でも作りますか。
(define-entry (find-number)
(let ((correct (remainder (sys-random) 100)))
(define (show-history history)
(div/ (h2/ "履歴")
(ol/
(node-set
(map (lambda (e) (li/ (x->string e)))
(reverse history))))))
(define (hit-viewer history)
(page "かずあてげーむ"
(h1/ "あたり!")
(h2/ (format "~a でした" correct))
(if (null? history)
(h2/ "しかもさいしょ!")
(show-history history))))
(define (viewer history guess)
(page "かずあてげーむ"
(div/
(h1/ "かずあてげーむ(0 〜 99)")
(if (null? history)
(p/ "さいしょ")
(div/
(h2/ (format "~a じゃないよ!" guess))
(if (integer? guess)
(h2/ "ヒント:もっと"
(if (> guess correct)
"ちいさいよ!" "おおきいよ!"))
(h2/ "読めないよ!"))
(show-history history)))
(form/cont/ (@@/ (cont
(entry-lambda (:keyword guess)
(let ((num (and guess
(read-from-string guess))))
(if (and
(integer? num)
(= num correct))
(hit-viewer history)
(viewer (cons num history) num))))))
(input/ (@/ (type "text") (name "guess")))
(input/ (@/ (type "submit")
(value "これだ!")))
))))
(viewer '() 0)))
form/cont ってのが form で入力したデータを受ける継続を用意します。
ちょっと複雑ですが、なれればどおってことないので考えてみてください。
もっともっともっと hello - オブジェクトデータベースを使ってみよう
Kahua アプリケーションは、標準で(つまり、何もしなくても)オブジェクトデ ータベースが利用できます。そのオブジェクトデータベースとは何か、というと、 Kahua においては「永続化クラスが作成できる」ということになります。さて、 では永続化クラスとはなんでしょうか。
通常、クラスのインスタンスの実体は、計算機のメモリにあります。つまり、そ の(UNIXでいう)プロセスが終了すると、そのデータが消えてしまいます。ずっ と残しておきたいデータはその都度ファイルなどに書き出さなければなりません。
しかし、永続化オブジェクトは、そのインスタンスの保存を勝手にやってくれま す。どのくらい勝手にやってくれるかというと、通常のスロットアクセス、スロ ットへの変数の代入を行うと、それが外部データベースに反映されます。つまり、 永続化オブジェクトを利用すると、いちいちファイルへ出力するような処理をか かなくても、たとえばプロセス再起動後もそのデータをアクセスできたり、複数 プロセスとデータを共有できたりします。
さて、オブジェクトデータベース、永続化オブジェクトやインスタンスなどとい う言葉が出てきましたが、お察しのとおり、これらは Gauche のオブジェクトシ ステムを利用します。これは、Common Lisp 由来の CLOS のサブセットになって います。Gauche のオブジェクトシステムを知らない人は、まぁこうやってデー タ構造を作るんだな、と思ってください。知ってる人は、Gauche のオブジェク トが勝手にシリアライズされるんだな、と思ってください。
では、とりあえずサンプルプログラムを作ってみましょう。「データベース」っ ていうくらいだから、データを保存するようなプログラムになりますよね。 hello にデータを保存するような処理を加えるわけですが、何がありまるかね。 とりあえず、アクセスカウンターでも作って見ますか。
アクセスされた回数を保存する、簡単な Gauche のクラスを作って、それを Kahua プログラムに組み込みます。
;; アクセスカウントを記録するためのクラス (define-class <access-counter> () ((counter :init-value 1)))
クラスはこんな感じでしょうか。Gauche のオブジェクトシステムに慣れてない 人のために、Java、C++、Ruby で書いてみました。
// Java
class AccessCounter{
public int counter;
public AccessCounter(){ counter = 1; }
}
// C++
class AccessCounter{
public:
int counter;
AccessCounter(){ coutner = 1; }
}
# Ruby
class AccessCounter
attr_accessor :counter
def initialize
@counter = 1
end
end
多分、こんな感じだと思います。
では、この簡単なクラスを永続化クラスに変更しましょう。
(define-class <access-counter> (<kahua-persistent-base>)
((counter :init-value 1
:allocation :persistent)))
このようになります。変更個所は「<kahua-persistent-base>クラスを継承し ていること」と、「counter slot の :allocation 属性に :persistent が 設定されたこと」です。
永続化クラスにするには、<kahua-persistent-base> クラスを継承するだけで大 丈夫なのですが、そのとき、永続化情報として保存されるのが :allocation 属 性に :persistent が指定されたスロット(Java でいうフィールド、C++ でいう メンバ変数、Ruby でいうインスタンス変数)が対象になります。
さて、ここでは <access-counter> クラスは counter スロットを勝手に保存し てくれてしまう凄いクラス(永続化クラス)になりました。簡単ですね。
最後に、hello プログラムに追加してみましょう。
(define-class <access-counter> (<kahua-persistent-base>)
((counter :init-value 1
:allocation :persistent)))
(define-method key-of ((obj <access-counter>))
"key")
(define-method count-up! ((obj <access-counter>))
(let1 count (ref obj 'counter)
(set! (ref obj 'counter) (+ count 1))
count))
(define (access!)
(let1 counter (find-kahua-instance <access-counter> "key")
(if counter
(x->string (count-up! counter))
(begin (make <access-counter>) "1"))))
(define-entry (hello-kahua)
(page "hello kahua!" ;; title
(div/
(h1/ "Hello Kahua!")
(p/ "あなたは" (access!) "人目の Helloer です"))))
なにやらまたゴテゴテと足されていますが、順番に調べていきます。key-of と いうメソッドを定義していますが、これはインスタンス検索のときのキーに使い ます。このキーは、この定義ではいつも "key" と返すので、いつ検索しても "key" という単語で検索できます。逆を言うと、複数のインスタンスを作っても、 最初にヒットしたものしか検索できません。その点、少し特殊な例になってしま いました。
ちなみに、このキーは String でなければなりません。
count-up! は、<access-counter> オブジェクトの counter を 1 増やします。
access! 関数はまず、 find-kahua-instance で <access-counter> クラスのイ ンスタンスを、キーを "key" にして検索します。もしなければ #f が入り、ヒ ットすればそのインスタンスが得られます。見つからなかった場合、新しいイン スタンスを make しています。
アクセスすると、「あなたは??人目の Helloer です」という文字が見えれば成 功です。また、このサーバを再起動してもこの数字は続きからカウントアップし ていきます。
オブジェクトデータベースの例も、まぁだいたいこんなもんですかね。
オブジェクトデータベース補足
今回の例ではインスタンスが一つしかない例を考えましたが、たとえば掲示板を 考えると、1投稿1オブジェクトにするのが普通です。また、各ページにアクセス カウンタを付けたいというときもあるでしょう。そのとき、アクセスカウンタオ ブジェクトが複数生成されるはずです。
このとき、複数の投稿、または複数のアクセスカウンタのうち、「どれか」を明 示するのが key-of メソッドになります。たとえば、この検索キーをアクセスカ ウンタの場合として「ページ名」としたければ、key-of メソッドをそのアクセス カウンタが置かれているページ名を返すメソッドとして定義しておきます(その ページ名は永続化されるスロットとして格納しておくことになるんでしょうね)。
key-of を定義しない場合、key-of は id へのシンプルなアクセッサ((ref obj 'id))になります。また、id slot へ何も設定しなければ、勝手に id が振られ ます。
あるクラスについての集合を得るには、 make-kahua-collection メソッドを使 います。クラスを指定すると、そのクラスについてデータベースに格納されてい るインスタンス全部のコレクションを返してくれます。このコレクションは、 (use gauche.collection) しておけば map や for-each のようなリストに対す る演算をそのまま適用できます。
hello 全部
作成した hello.kahua のソースを載せてみます。
(define (page ttl . elems)
(html/ (head/ (title/ ttl))
(body/ (node-set elems))))
(define-class <access-counter> (<kahua-persistent-base>)
((counter :init-value 1
:allocation :persistent)))
(define-method key-of ((obj <access-counter>))
"key")
(define-method count-up! ((obj <access-counter>))
(let1 count (ref obj 'counter)
(set! (ref obj 'counter) (+ count 1))
count))
(define (access!)
(let1 counter (find-kahua-instance <access-counter> "key")
(if counter
(x->string (count-up! counter))
(begin (make <access-counter>) "1"))))
(define-entry (hello-kahua)
(page "hello kahua!" ;; title
(div/
(h1/ "Hello Kahua!")
(p/ "あなたは" (access!) "人目の Helloer です"))))
(define-entry (world)
(page "hello kahua! - world"
(h1/ "Hello Kahua!")
(h2/ "Hello World!")))
(define-entry (counter)
(define (viewer count)
(page "hello kahua! - counter"
(h1/ "Hello Kahua!")
(h2/ (format "count is ~a" count))
(p/
(a/cont/ (@@/ (cont
(lambda () (viewer (+ count 1)))))
"inc count") " , "
(a/cont/ (@@/ (cont
(lambda () (viewer (- count 1)))))
"dec count")
)))
(viewer 0))
(define-entry (find-number)
(let ((correct (remainder (sys-random) 100)))
(define (show-history history)
(div/ (h2/ "履歴")
(ol/
(node-set
(map (lambda (e) (li/ (x->string e)))
(reverse history))))))
(define (hit-viewer history)
(page "かずあてげーむ"
(h1/ "あたり!")
(h2/ (format "~a でした" correct))
(if (null? history)
(h2/ "しかもさいしょ!")
(show-history history))))
(define (viewer history guess)
(page "かずあてげーむ"
(div/
(h1/ "かずあてげーむ(0 〜 99)")
(if (null? history)
(p/ "さいしょ")
(div/
(h2/ (format "~a じゃないよ!" guess))
(if (integer? guess)
(h2/ "ヒント:もっと"
(if (> guess correct)
"ちいさいよ!" "おおきいよ!"))
(h2/ "読めないよ!"))
(show-history history)))
(form/cont/ (@@/ (cont
(entry-lambda (:keyword guess)
(let ((num (and guess
(read-from-string guess))))
(if (and
(integer? num)
(= num correct))
(hit-viewer history)
(viewer (cons num history) num))))))
(input/ (@/ (type "text") (name "guess")))
(input/ (@/ (type "submit")
(value "これだ!")))
))))
(viewer '() 0)))
(initialize-main-proc hello-kahua)
http : //.../kahua.cgi/hello で hello-kahua が呼ばれ、http: //.../kahua.cgi/hello/find-number 、http : //.../kahua.cgi/hello/counter 、 http : //.../kahua.cgi/hello/world でそれぞれ find-number 、counter 、world 手続きが呼ばれることになります。
Kahua プログラミング環境
Kahua にはいろいろ便利なユーティリティが付属しています。本項ではそれらに ついて簡単に説明します。
kahua-admin の利用
kahua-admin は動いている Kahua システムに対する管理機能を提供します。
サーバの再起動、再読み込み、サーバへの接続(Schemeの評価可能な repl でサ ーバプロセスに対するアクセスが可能)などが行えます。
これを利用することで、kahuaプログラムのリロードのために kahua-spvr の再 起動を行わなくてよくなります。
詳細: kahua-admin
kahua-shell の利用
kahua-shell は、あるサーバへ接続可能にします(Schemeの評価可能な repl で サーバプロセスに対するアクセスが可能)。また、このアクセスには認証をかけ ることができます。
詳細: kahua-shell
Emacs との連携
kahua-shell は emacs と一緒に使うことを主に考えています。emacs の scheme-mode の scheme-send-* 機能を利用することで、動作中のサーバの挙動を 簡単に変更することができます。emacs を使っている人は、是非試してください。
詳細: kahua-shell
ユーザ別 Kahua 環境の利用
本番運用のための Kahua サーバと、自分の実験用の Kahua サーバを分けること ができます。
詳細: UserExclusiveMode?
テストの作成
作った Kahua プログラムのテストを、簡単なパターンマッチング言語を使って 作ることができます。
詳細: kahua.test.xml kahua.test.worker
終わりに
これでチュートリアルは終わりです。百聞は一見にしかず、是非一度 Kahua を 試してみてください。
もし、わからないところがあれば、お気軽にメーリングリストなどでご質問くだ さい。
メーリングリスト:Mailing List
Kahua は発展途上です。あなたが望めばあなたも Kahua core の開発者! とり あえずメーリングリストにご参加ください。
Kahua の情報は今後も http://www.kahua.org/ で公開していく予定です。
Happy Kahua Programming!