2013-04-02 31 views
2

在Clojure中,一個if表達的不匹配條件分支不評估假分支防止宏膨脹,因此沒有異常在評價以下表達式拋出然而,宏仍然會評估if前擴大,所以你仍然可以得到例外,像這樣:中的表達是否

=> (if nil (proxy [nil] [])) 
CompilerException java.lang.NullPointerException, compiling:(NO_SOURCE_PATH:1) 

我寫了其中接口的名稱有時會作爲ARG提供一個宏,在哪種情況下e宏將生成撥打proxy的代碼。其他時候,接口參數將會是nil,然後宏擴展到類似(if nil (proxy [nil] []),所以我得到了上述例外。一個SSCE可能是:

=> (defmacro make-listener [listener-name & methods] 
    `(if ~listener-name 
     (proxy [~listener-name] [] 
      [email protected](map (fn [m] `(~m [e#])) methods)))) 
#'user/make-listener 
=> (make-listener java.awt.event.ActionListener actionPerformed) 
#<Object$ActionListener$46793e3a [email protected]> 
=> (make-listener nil) 
CompilerException java.lang.NullPointerException, compiling:(NO_SOURCE_PATH:1) 

如何在不提供接口參數的情況下以不引發異常的方式編寫宏?

回答

4

如果listener-name是零,那麼宏應該什麼也不做,即你需要在宏擴展時檢查listener-name(而不是在宏發出的代碼中)。

(defmacro make-listener [listener-name & methods] 
    (if listener-name 
    `(proxy [~listener-name] [] 
     [email protected](map (fn [m] `(~m [e#])) methods)))) 
+0

工作,謝謝! – OpenSauce

+0

安庫爾,我不明白爲什麼你的作品,但醬不是......不應該在醬的例子中的'如果'條款延遲代理的創建以你的方式嗎? –

+0

@jk:'proxy'是一個宏,它在被編譯器宏擴展時引發null異常。 null異常是編譯時異常而不是運行時異常。 – Ankur