2

Clojureマクロを学習中ですが、このマクロでmacroexpand-1を使用しようとすると、NullPointerExceptionが発生します。

(def config {:ns 'bulbs.neo4jserver.client, 
             :root-uri "http://localhost:7474/db/data/"})
(def data {:name "James"})

(defmacro create
  [config data]
  `(~(ns-resolve (:ns config) 'create-vertex) config data))

(macroexpand-1 '(create config data))

これをコンパイルしようとすると、次の結果が返されます。

 Unknown location:
   error: java.lang.NullPointerException

 Compilation failed.

しかし、マクロの本体を評価する...

`(~(ns-resolve (:ns config) 'create-vertex) config data)

...これを返します...

(#'bulbs.neo4jserver.client/create-vertex bulbs.vertices/config bulbs.vertices/data)

...それが私が欲しいと思うものです。

更新:手動で置き換える(:ns config)'bulbs.neo4jserver.client、エラーはなくなります-どうすれば(:ns config)プレイを上手くできますか?

4

2 に答える 2

3

マクロ展開時間と実行時の情報を混在させようとしています。ローカルの「config」には#'config varの内容は含まれていませんが、代わりにシンボル'configです。

エラーメッセージだけでなく、完全なスタックトレースを見ると、ns-resolveにnilが渡されていることがわかります。

user=> (pst)
NullPointerException 
        java.util.concurrent.ConcurrentHashMap.get (ConcurrentHashMap.java:796)
        clojure.lang.Namespace.find (Namespace.java:188)
        clojure.core/find-ns (core.clj:3657)
        clojure.core/the-ns (core.clj:3689)
        clojure.core/ns-resolve (core.clj:3879)
        clojure.core/ns-resolve (core.clj:3876)
        clj.core/create (NO_SOURCE_FILE:7)

以下を理解すると、元の問題を理解できます。

user=> (def bar [1 2 3])
user=> (defmacro foo [x] [(class x) (pr-str x)])
user=> (foo (get bar 2))
[clojure.lang.PersistentList "(get bar 2)"]
于 2012-05-15T16:46:36.883 に答える
1

そもそもなぜこれがマクロなのか?この場合、通常の機能で動作するようです。

config入力したリテラル値にバインドされていることを忘れないでください。

(def c {:ns 'foo})  
(create c 1)

config実行時に'c参照されるマップではなく、単なるになります。c

于 2012-05-15T16:47:13.183 に答える