【问题标题】:Clojure macro with try block error: cannot bind qualified name带有 try 块错误的 Clojure 宏:无法绑定限定名
【发布时间】:2017-12-14 21:37:41
【问题描述】:

我正在尝试定义一个宏,该宏编写代码来为传入的表达式执行 try catch 块。

(defmacro safe
     [expression]
     `(try
          ~expression 
          (catch Exception e (str "caught exception: " (.getMessage e)))
      )
)

宏写得很好,但是当我对其进行一些测试时,我收到以下编译器错误

seminar.core=> (def v (safe (/ 1 0)))
CompilerException java.lang.RuntimeException: Can't bind qualified name:seminar.core/e, compiling:(/private/var/folders/6f/q7lhngtn45q_xpzd_24gjp2h0000gn/T/form-init2350735096437822603.clj:1:8) 

seminar.core=> (def v (safe (/ 10 2)))
CompilerException java.lang.RuntimeException: Can't bind qualified name:seminar.core/e, compiling:(/private/var/folders/6f/q7lhngtn45q_xpzd_24gjp2h0000gn/T/form-init2350735096437822603.clj:1:8) 

这就是宏的行为方式

user> (def v (safe (/ 1 0)))
user> v
#<ArithmeticException java.lang.ArithmeticException: Divide by zero>
user> (def v (safe (/ 10 2)))
user> v
5

【问题讨论】:

    标签: clojure macros


    【解决方案1】:

    您需要在宏中为e 生成一个唯一符号:

    (defmacro safe
      [expression]
      `(try ~expression
         (catch Exception e#
           (str "caught exception: " (.getMessage e#)))))
    

    然后你得到想要的行为:

    (safe (/ 1 0))
    => "caught exception: Divide by zero"
    

    请参阅this 相关问题。 # 后缀是 gensym 的特殊简写。这样做是必要的一个原因是,当宏展开时,宏中的绑定不会覆盖其他同名绑定。

    【讨论】:

      【解决方案2】:

      最好扩展宏以采用任意数量的表达式返回最后一个作为肯定结果。我的版本是:

      (defmacro safe [& body]
        `(try
           (do ~@body)
           (catch Exception e#
             (println (format "Error: %s" (.getMessage e#))))))
      

      使用示例:

      (safe
       (+ 1 2)
       (println "hey")
       (/ 42 0))
      

      它会在导致错误的表单之前评估所有表单。结果将是 nil 值,并在控制台中打印错误消息:

      hey
      Error: Divide by zero
      nil
      

      【讨论】:

        猜你喜欢
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-16
        • 2019-02-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多