ハイブリッドマクロは、マクロと手続きを合わせたものです。 ハイブリッドマクロに束縛されているシンボルがフォームの最初のポジションにある場合、 それはマクロのように振る舞い、マクロ展開器によって展開されます。 シンボルがその他の場所に現れた場合は、実行時に手続きへと評価されます。
これは、いわゆる「コンパイラマクロ」を実現するのに使えます。つまり、
コンパイル時に引数を調べ好きなようにフォームを変換できます。
それ以外の場合は普通の手続きへの束縛のように振る舞うので、
例えばmap
の引数として渡すことができます。
variableを通常のScheme値とマクロの両方に束縛します。 コンパイル時にtransformer-specが評価されます。それはコンパイル時環境において マクロを返さなければなりません。そして、マクロ展開用にvariableに束縛されます。 一方exprは実行時に評価され、実行時の値としてvariableに束縛されます。
マクロ展開器は、入力フォームに展開の必要がなければそれをそのまま
(入力フォームとeq?
になるオブジェクトとして)返すことができます。
その場合、Gaucheはフォームを単なる手続き呼び出しとしてコンパイルし、
exprの実行時の値が呼び出されます。
註: ハイブリッドマクロでやりたいことが、手続き本体をインライン展開するだけなら、
define-inline
を使った方が良いです。定義参照。
構文についての註: 伝統的にLispでは、コンパイラマクロを定義するフォームは 通常の手続きの束縛を定義するフォームと別でした。
しかし、一つの識別子に別々のフォームで複数の定義を与えるのは、 プログラムの意味に曖昧性を持ち込みます。たとえば通常の定義とコンパイラマクロの定義が 別のモジュールに分かれていたら? あるいはどちらか一方が再定義されたら? Gaucheではひとつのフォームで束縛を決定してしまう方が良いと判断しました。