2

Clojure では、if条件に一致しない式の分岐は評価されないため、以下の式の評価で例外はスローされません。

=> (if nil (/ 1 0))
nil

ただし、マクロは を評価する前に展開されるため、次のifような例外が発生する可能性があります。

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

インターフェイスの名前が引数として提供されることがあるマクロを作成しています。この場合、マクロは への呼び出しのコードを生成しますproxy。それ以外の場合は、インターフェイス引数が になりnil、マクロが のようなものに展開される(if nil (proxy [nil] [])ため、上記の例外が発生します。SSCE は次のようになります。

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

インターフェイス引数が指定されていない場合に例外をスローしない方法でマクロを作成するにはどうすればよいですか?

4

1 に答える 1

4

listener-name が nil の場合、マクロは何もしません。つまり、マクロ展開時に listener-name をチェックする必要があります (マクロが発行するコードではありません)。

(defmacro make-listener [listener-name & methods]
  (if listener-name
     `(proxy [~listener-name] []
       ~@(map (fn [m] `(~m [e#])) methods)))) 
于 2013-04-02T08:56:51.323 に答える