8

私はちょうどsharpsignコロンリーダーマクロを読んでいて、gensymと非常によく似た効果があるように聞こえました

Sharpsignコロン:「インターンされていないシンボルを導入します」

Gensym: "インターンされていない新鮮なシンボルを作成して返します"

というわけで簡単なテスト

CL-USER> #:dave
; Evaluation aborted on #<UNBOUND-VARIABLE DAVE {1002FF77D3}>.
CL-USER> (defparameter #:dave 1)
#:DAVE
CL-USER> #:dave
; Evaluation aborted on #<UNBOUND-VARIABLE DAVE {100324B493}>.

それが失敗するように冷却してください。

いよいよマクロテスト

(defmacro test (x)
  (let ((blah '#:jim))
    `(let ((,blah ,x))
       (print ,blah))))

CL-USER> (test 10)

10 
10
CL-USER>

甘いので、ゲンシムのような方法で使用できます。

私には、これは明らかに同一の結果で gensym よりもきれいに見えます。重要な詳細が欠けていると確信しているので、私の質問は、それは何ですか?

4

2 に答える 2

9

マクロが展開されるたびに、同じシンボルが使用されます。

(defmacro foo () `(quote #:x))
(defmacro bar () `(quote ,(gensym)))

(eq (foo) (foo)) => t
(eq (bar) (bar)) => nil

Gensym は評価されるたびに新しいシンボルを作成しますが、シャープ コロンは読み取り時にのみ新しいシンボルを作成します。

シャープ コロンを使用しても問題が発生する可能性はほとんどありませんが、まれにバグを見つけるのがほぼ不可能になるケースがいくつかあります。常に gensym を使用して、最初から安全である方がよいでしょう。

シャープコロンのようなものを使いたい場合は、defmacro を参照してください。Let Over Lambda のマクロ。

于 2015-02-02T11:10:38.623 に答える
7

GENSYMのようMAKE-SYMBOLです。違いは、GENSYMカウントアップによる派手な命名をサポートすることです -> したがって、シンボルは一種の一意の名前を持ちます。これにより、たとえばマクロ展開で gensyms がある場合のデバッグが少し簡単になります。

#:foo読者のための表記です。

したがって、これらとリテラル表記を作成する関数があります。*print-circle*が true の場合、ある種の同一性が s-expressions: で保持される可能性があることに注意してください#(#1=#:FOO #1#)

(a . b)一般に、これはand (cons 'a 'b)#(a b)and ...に似てい(vector 'a 'b)ます。1 つはリテラル データで、もう 1 つは新しいオブジェクトを作成 ('cons') するフォームです。

マクロを見ると、主な問題は、マクロをネストして使用すると問題が発生する可能性があることです。字句的にも動的にも。

  • 字句的には、リバウンドである同じ変数である可能性があります。

  • 動的に、それが特別な変数である場合、再バインドすることもできます

マクロ展開時に生成されたシンボルを使用すると、展開された異なるコードがバインドを共有しないことが保証されます。

于 2015-02-02T11:09:41.337 に答える