3

編集:私の例では、 =>「評価する」を->意味し、「下に展開する」を意味し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 つの例は同じ構造を共有しているように見えますが、評価結果には一貫性がないようです。

4

1 に答える 1

1

私は自分のエラーを見ていると思います。上記のマクロ展開の 2 行目は、実際には次のようになります。

`(LET (,`(,#:G939 ,FROM) ,`(,#:G940 ,TO))

これは、SBCL が示すものと同等です。

于 2013-08-24T13:06:19.443 に答える