2012-05-15 52 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

相關問題