【问题标题】:Prevent macro expansion in false branch of if expression防止 if 表达式的错误分支中的宏扩展
【发布时间】:2013-04-02 08:24:25
【问题描述】:

在 Clojure 中,不匹配条件的 if 表达式的分支不会被计算,因此在计算以下表达式时不会引发异常:

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

但是,在评估 if 之前,宏仍然会被扩展,因此您仍然可以得到如下异常:

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

我正在编写一个宏,它的接口名称有时会作为 arg 提供,在这种情况下,宏将生成调用 proxy 的代码。其他时候,接口 arg 将为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) 

如何在没有提供接口 arg 时以不引发异常的方式编写宏?

【问题讨论】:

    标签: macros clojure expansion


    【解决方案1】:

    如果 listener-name 为 nil,那么宏应该什么都不做,即您需要在宏展开时检查 listener-name(不在宏发出的代码中)。

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

    【讨论】:

    • Ankur,我不明白为什么你的工作,但酱的没有。酱的例子中的“if”子句不应该像你的那样延迟代理的创建吗?
    • @jk: proxy 是一个宏,在编译器对其进行宏扩展时会抛出空异常。空异常是编译时异常而不是运行时异常。
    猜你喜欢
    • 2011-12-25
    • 2015-01-27
    • 2011-09-18
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多