2012-05-15 24 views
2

我在学习的Clojure宏的过程中,我越来越想在这个宏中使用macroexpand-1,当一个NullPointerException异常:为什么在这个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)发挥不错?

回答

3

您正在尝试混合宏展开时间和运行时信息。本地“配置”不包含#'config var的内容,而是符号'config。

如果你看一下完整的堆栈跟踪,不只是错误信息,你会看到NS-决心正在传递一个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)"] 
+0

啊。谢谢蒂姆。 – espeed

1

为什么这是一个宏?在这种情况下,这似乎是一个正常的功能。

记住config必将给您输入的文字值,所以如果你做

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

config将是刚刚'c,而不是在运行时c引用的地图。

+0

我试图避免重复调用(ns-resolve)。 – espeed

相关问题