3

評価したら

(def ^:macro my-defn1 #'defn)

「my-defn1」という名前のマクロが定義されており、「defn」と同じように使用できます。

ただし、代わりに評価すると

(if true
  (def ^:macro my-defn2 #'defn))

「my-defn2」の var には :macro メタデータ セットがなく、マクロとして使用できません。「def」形式は前のケースと同じですが。

完全なコードは次のとおりです ( http://cljbin.com/paste/52322ba5e4b0fa645e7f9243 ):

(def ^:macro my-defn1 #'defn)

(if true
  (def ^:macro my-defn2 #'defn))

(println (meta #'my-defn1))    ; => contains :macro

(println (meta #'my-defn2))    ; => doesn't contain :macro!

(my-defn1 hello1 []
          (println "hello 1"))

(hello1)                       ; => prints "hello 1"

(my-defn2 hello2 []            ; => CompilerException: Unable to resolve 
  (println "hello 2"))         ;    symbol: hello2 in this context

動作が異なる理由は何ですか?

4

1 に答える 1

1

Clojure の def は、実際には条件付きで適用することはできません。def のドキュメントは、IMO でその部分の強度が不十分です。スタイルが悪いだけでなく、あらゆる種類の微妙な問題を引き起こす可能性があります.

def は最上位でのみ使用するか、最上位の adoまたはletform で使用する必要があります。条件付きで def を適用すると、機能が次のようなものに分割されdeclare、その後の conditionaldefになりますが、常に期待/好きな方法であるとは限りません。

ここで最上位で def を使用し、条件付きで を使用する方がよい場合がありますalter-var-root。または使用します(def my-var (if .. .. ..))。グローバルな定義を「消滅」させたい理由を考えてみてください。

于 2013-09-16T06:59:10.350 に答える