我发现在clj和cljs中定义一个宏来处理错误是非常棘手的。我以为只需要用js/Error替换Exception就可以了,但实际上比这更加复杂。
起初,我尝试了以下代码:
现在它在cljs中可以工作,但在clj中却不行!!! 经过一些试验,我发现JVM Clojure(显然)不允许您间接引用异常类。您必须直接通过名称引用
我的问题是,是否有更好的方法?为什么JVM Clojure不允许间接引用异常类,但ClojureScript允许? 更新 在ClojureMostly的帮助下,我已将宏重构如下,并且它可以工作:
起初,我尝试了以下代码:
(defmacro my-macro
[& forms]
`(try
~@forms
(catch #?(:clj Exception :cljs js/Error) e#
,,,)))
但是每次这样做都会产生一个异常
。我很快意识到问题在于宏被调用时正在编译我的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#
,,,)))