(rontolisp) docs
← 特殊形式

defmacro

(defmacro name lambda-list body...)

name という名前のユーザーマクロを定義し、名前シンボルを返します。マクロ呼び出しは引数フォームを評価せずに受け取ります。body は展開時にパラメータへ生のフォームを束縛して実行され、返したフォーム(展開形)が呼び出しの代わりに評価されます。ラムダリストはマクロラムダリストで、destructuring-bind と同様に引数フォームへ分配束縛されます: 必須位置ではパターンをネストでき、&optional(デフォルト値付き)、&rest/&body&key&aux をサポートします。&whole&environment はサポートされません。このような拡張ラムダリストではマッチングは寛容です(足りない位置は nil に束縛され、余ったフォームは無視されます)。プレーンなラムダリスト(必須パラメータと末尾の &rest/&body 1 つ)では厳密な引数個数チェックが維持されます。標準オペレータ(whensetf など)は再定義できず、マクロは関数値を持ちません(#'name はエラーです)。

マクロ本体は通常、バッククォートのテンプレート構文で展開形を組み立てます。この構文はプログラム中のどこでも使えます。

  • `form はカンマで unquote された箇所を除き form をクォートします
  • ,exprexpr の値を挿入します
  • ,@exprexpr の値(リスト)を周囲のリストに継ぎ足し(splice)ます

ネストしたバッククォート(バッククォートテンプレートの中の別のバッククォート)はサポートされ、読み取り時に完全に展開されるため、once-only のような古典的なマクロ書きマクロも動作します。マクロ本体で変数捕捉のない一時変数を生成するには gensym を、展開結果を調べるには macroexpand-1/macroexpand を使用してください。

インタープリタはマクロ呼び出しを評価時に展開します(そのため defmacro は REPL や load/eval 経由でも動作します)。コンパイルパスでは、CLI が JVM/WASM コンパイラの実行前にすべてのマクロ呼び出しを完全展開して定義を取り除くため、コンパイル出力には通常のフォームだけが含まれます。したがってコンパイル済みプログラムの実行時 eval/readdefmacro やバッククォート文字を認識せず、マクロは最初の使用より前に定義されている必要があります。