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将是 just ,而不是运行时'c引用的地图。c

于 2012-05-15T16:47:13.183 回答