関数 list を呼ぶ回数だけを考えても、あまり大きなマクロを書くのは、うまくありま せん。前に記した for の例は(妥当な)リストの深さの(ほぼ)限界を示しています。 (このような)フォームを書くのをたやすくするため、マクロ ` (バッククォートと呼 ぶ)が与えられています。
バッククォートはリストをクォートしますが、リストの要素を選択的に評価します。こ れは(その一番単純なフォームにおいて)特殊フォーム quote と同じ働きをします。以 下に示す 2つのフォームは、同じ結果になります。
(` (a list of (+ 2 3) elements)) => (a list of (+ 2 3) elements) (quote (a list of (+ 2 3) elements)) => (a list of (+ 2 3) elements)
バッククォートに対するアーギュメント中に特別なマーカー (,) を入れることで、 アーギュメントの(評価させたい)部分のみを評価させることができます。
(list 'a 'list 'of (+ 2 3) 'elements) => (a list of 5 elements) (` (a list of (, (+ 2 3)) elements)) => (a list of 5 elements)
特別なマーカー (,@) を用いることで、リストを評価し(要素にするのではなく) 結果 のリストに組み込む(訳注:splice in)こともできます。
(cons 1 (list (+ 1 1) (+ 1 2))) => (1 2 3) (` (1 (,@ (list (+ 1 1) (+ 1 2))))) => (1 2 3)
;; もっとひどい例
(cons 'a (cons 'list (cons 'of (append (list (+ 2 3)) '(elements))))) => (a list of 5 elements) (` (a list of (,@ (list (+ 2 3))) elements)) => (a list of 5 (elements)) ????? => (a list of 5 elements)
これにより、for マクロは (より明確に)次のように書き直すことができます。
(defmacro for (var from init to final fo &rest body) "Execute a simple for loop: (for i from 1 to 10 do (print i))." (` (let (( (, var) (, init) )) (while (<= (, var) (, final)) (,@ body) (inc (, var)) )))) => for
Macro: ` list
このマクロは、quote が行なうように list を返します。違いは、特別なマーカー (,) で始まるサブリストはその 2番目の要素を評価し、特別なマーカー (,@) で始 まるサブリストはその 2番目の要素を評価しその結果を新しく作られるリストに組 み込む点です。
このような特別なマークを付けられたサブリストが 2つ以上の要素を持つ場合、そ の要素は無視されることになります。
??避けられなくてはいけない微妙なバグがいくつかあります。以下のフォームは期 待するようには動きません。
(` (a . (, 1))) => (a \, 1) ; (a . 1) でない
(` [a (, 1) c]) -> ERROR: Wrong type argument ; [a 1 c] でない (` (, 2)) => (\, 2) ; 2 でない