如何在Clojure宏中封装异常?

4

我希望能够捕获由系统或用户(无论哪个)引发的异常,并将其包装成返回某些值的形式。

我写了一个宏来实现,但是它并没有起作用。

宏:

(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

2个回答

7
宏是返回待评估代码的函数,因此您可以像这样编写 safe-fn
(defmacro safe-fn
  [form]
  `(try
     ~form
     (catch Throwable ~'_
       1)))

例子:

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

有关宏和特别是使用它们捕获异常的更多细节,请参见我对这个问题的回答。


2
来自Tupelo库的宏with-exception-default正是您想要的:

异常情况下的默认值

有时您知道某个操作可能导致异常,并且希望将异常转换为默认值。这就是您需要的情况:

(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

这个功能在tupelo.parse中得到了很好的应用,其中你会发现一些像这样的函数:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接