【发布时间】:2017-01-07 00:26:09
【问题描述】:
我发现在 clj 和 cljs 中定义一个宏来进行错误处理非常棘手。我以为将Exception 与js/Error 交换是一件简单的事情,但结果却比这更复杂。
一开始我是这样尝试的:
(defmacro my-macro
[& forms]
`(try
~@forms
(catch #?(:clj Exception :cljs js/Error) e#
,,,)))
但这每次都会产生Exception。我很快意识到问题是在编译我的 cljs 文件期间调用了宏,这发生在 clj 环境中。因此,我必须让宏返回一个在运行时解析为正确异常类的表单。我试过这个:
(def exception-class
#?(:clj Exception :cljs js/Error))
(defmacro my-macro
[& forms]
`(try
~@forms
(catch exception-class e#
,,,)))
现在它在 cljs 中有效,但在 clj 中无效!!!经过一些实验,我发现 JVM Clojure(显然)不允许您间接引用异常类。您必须直接按名称引用Exception。
所以最后,我决定了:
(def fake-java
#?(:cljs (clj->js {:lang {:Exception js/Error}})))
(defmacro my-macro
[& forms]
`(let [~'java fake-java]
(try
~@forms
(catch Exception e#
,,,))))
Exception 扩展为 java.lang.Exception,现在在运行时在 clj 和 cljs 中解析为正确的异常类。
我的问题是,有没有更好的方法呢?为什么 JVM Clojure 不允许间接引用异常类,而 ClojureScript 允许?
更新
在 ClojureMostly 的帮助下,我已经像这样重构了宏,并且它可以工作:
(defmacro my-macro
[& forms]
`(try
~@forms
(catch ~(if (:ns &env) 'js/Error 'Exception) e#
,,,)))
【问题讨论】:
标签: clojure clojurescript