編集:私の例では、 =>
「評価する」を->
意味し、「下に展開する」を意味しmacroexpand-1
ます。
Common Lisp のネストされた逆引用符について頭を悩ませようとしていますが、他のいくつかの SO の質問のおかげで、理解に非常に近づいていると思います彼ら)。最後に 1 つだけ私を悩ませていることがあります。検討:
`(a `(b ,,@(list 'c 'd)))
=> (a `(b ,c ,d))
CLHS で逆引用符で囲まれたフォームを展開するためのアルゴリズムに従って、上記の最初のフォームの (読み取り時) 展開プロセスを実行しました。実際、その展開から得られたフォームを評価すると、同等の結果が得られます。once-only
ここで、 Peter Seibel の優れた著書で与えられた の定義を考えてみましょう。
(defmacro once-only ((&rest names) &body body)
(let ((gensyms (loop for n in names collect (gensym))))
`(let (,@(loop for g in gensyms collect `(,g (gensym))))
`(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n)))
,(let (,@(loop for n in names for g in gensyms collect `(,n ,g)))
,@body)))))
その定義を考えると、SBCL は次のマクロ展開を示します。
(once-only (from to)
`(do ((,var ,from (next-prime (+ 1 ,var))))
((>= ,var ,to))
,@body)))
-> (LET ((#:G939 (GENSYM)) (#:G940 (GENSYM)))
`(LET ((,#:G939 ,FROM) (,#:G940 ,TO))
,(LET ((FROM #:G939) (TO #:G940))
`(DO ((,VAR ,FROM (NEXT-PRIME (+ ,1 ,VAR)))) ((>= ,VAR ,TO)) ,@BODY))))
今、私の問題は、展開されたフォームの 2 行目です。そうではありませんか:
`(LET (,(,#:G939 ,FROM) ,(,#:G940 ,TO))
?
上記の最初の例の の評価が,,@
、リストから結合された要素にカンマを「分配」する方法を見てください(c d)
。なぜここでそれが起こらないのですか?2 つの例は同じ構造を共有しているように見えますが、評価結果には一貫性がないようです。