如何在 Clojure 宏中包装异常?

How to wrap Exception in Clojure Macro?

我想包装系统或用户抛出的异常(无关紧要)并将其强制为 return 某个值。

我为它写了宏,但它不起作用。

宏:

(defmacro safe-fn
  [form]
  (try
    `(do ~form)
    (catch Throwable e
      1)))

用法:(safe-fn (throw (RuntimeException. "Try me!")))

实际输出:RuntimeException Try me! clojure-brave-and-true.core/eval2219 (form-init6122238559239237921.clj:1)

期望的输出:1

宏只是 return 待评估代码的函数,因此您可以这样写 safe-fn

(defmacro safe-fn
  [form]
  `(try
     ~form
     (catch Throwable ~'_
       1)))

示例:

(safe-fn (throw (RuntimeException. "Try me!")))
;=> 1

查看我对 的回答,了解有关宏的更多详细信息,特别是使用它们捕获异常的详细信息。

来自 the Tupelo library 的宏 with-exception-default 完全符合您的要求:

Default Value in Case of Exception

Sometimes you know an operation may result in an Exception, and you would like to have the Exception converted into a default value. That is when you need:

(with-exception-default default-val & body)
  Evaluates body & returns its result.  In the event of an exception the
  specified default value is returned instead of the exception."

(with-exception-default 0
  (Long/parseLong "12xy3"))
;=> 0

This feature is put to good use in tupelo.parse, where you will find functions that work like this:

(parse-long "123")                  ; throws if parse error
;=> 123
(parse-long "1xy23" :default 666)   ; returns default val if parse error
;=> 666