Gaucheで超高生産性Webアプリ!
マクロ
templateはマクロ定義です。templ-render関数を呼び出しには、(templ-render "list.tmpl" '(a b) (list a b))のように変数名のリストとその値のリストを渡します。しかし、毎回同じようにa bを書くのは無駄ですよね。このような場合、マクロを使うと(template "list.tmpl" a b)を簡潔に記述できるようになります。
マクロが呼び出されると、マクロ定義に書かれている式を評価し、その結果のS式をさらに評価します。また引数は評価せず、そのままマクロ定義に渡されます。
この説明だけでは分かりにくいので、templateマクロを例にマクロの動作を見ていきましょう。
マクロの動作
1. まず、(template "list.tmpl" a b)が呼び出されます。
2. templateマクロの定義にある`は、'と同様に続くS式を評価しないで戻します。ただし、S式内の,の次の1つのS式は評価され、結果で置き換えられます。例えば`(+ a ,(+ 1 2))は、(+ a 3)になります。また,@は次のS式のリストを分解して置き換えます。例えばxの値が(1 2 3)のとき、`(+ ,@x)は(+ 1 2 3)になります。したがって、(quote ,args)は(quote (a b))に、(list ,@args)は(list a b)に置き換えられます。
3. そこで`(templ-render ...)は、(templ-render "list.tmpl" (quote (a b)) (list a b))に置き換えられます。
4. そして、置き換え結果の(templ-render "list.tmpl" (quote (a b)) (list a b))が実行されます。
また、マクロに限らず関数定義でも同じですが、パラメータ定義が(func arg1 . rest_args)となっている場合、2つ目以降の引数がリストの形でrest_argsにわたります。例えば、(func 1 2 3)という呼び出しに対し、(func arg1 . rest_args)では、arg1 は1、rest_argsは(2 3)になります。
ここで説明したマクロは「伝統的なマクロ」と呼ばれるもので、Schemeの規格にはありません。Scheme(R5RS)には、define-syntaxで定義されるパターン言語に基づく「健全なマクロ」があります、
このdefine-syntaxはできることに限界があり、GaucheにはCommonLispをはじめとした従来のLispにある「伝統的なマクロ」も備わっています。「伝統的なマクロ」は、プログラムの記述を簡潔にしたり、新しい構文を導入できたりと大変強力です。
しかし、マクロ定義内で使っているシンボル(変数)と生成されるS式内で使われるシンボルの競合が発生したりするので注意が必要です。マクロの使い方については、「On Lisp(http://user.ecc.u-tokyo.ac.jp/~tt076524/onlispjhtml/)」が大変参考になります。
さて、次回はWebアプリケーションの機能を強化していき、Gaucheの特徴である「継続」を使ったCOOLなWebアプリケーションを作っていきましょう!