我正在学习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)
玩得很好?
答案 0 :(得分: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)"]
答案 1 :(得分:1)
为什么这首先是一个宏?在这种情况下,这似乎是正常的功能。
请记住,config
与您输入的文字值绑定,因此如果您执行
(def c {:ns 'foo})
(create c 1)
config
将只是'c
,而不是c
在运行时引用的地图。