首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >cljc宏中的错误处理

cljc宏中的错误处理
EN

Stack Overflow用户
提问于 2017-01-07 00:26:09
回答 2查看 556关注 0票数 6

我发现在cljcljs中定义一个宏来进行错误处理是非常棘手的。我以为这是一个简单的问题,将Exceptionjs/Error交换,但结果却比这更复杂。

一开始,我试过这个:

代码语言:javascript
复制
(defmacro my-macro
  [& forms]
 `(try
    ~@forms
    (catch #?(:clj Exception :cljs js/Error) e#
      ,,,)))

但这每次都产生了Exception。我很快意识到问题是在编译我的cljs文件时调用了宏,这发生在clj环境中。因此,我必须让宏返回一个在运行时解析为正确异常类的表单。我试过这个:

代码语言:javascript
复制
(def exception-class
  #?(:clj Exception :cljs js/Error))

(defmacro my-macro
  [& forms]
 `(try
    ~@forms
    (catch exception-class e#
      ,,,)))

现在它在cljs中工作,但在clj!经过一些实验之后,我发现JVM Clojure (显然)不允许间接引用异常类。您必须直接按名称引用Exception

最后,我决定:

代码语言:javascript
复制
(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,它现在在运行时解析为cljcljs中的正确异常类。

我的问题是,有更好的方法吗?为什么JVM不允许间接引用异常类,而ClojureScript允许引用异常类呢?

更新

在ClojureMostly的帮助下,我对宏进行了如下重构,它运行如下:

代码语言:javascript
复制
(defmacro my-macro
  [& forms]
 `(try
    ~@forms
    (catch ~(if (:ns &env) 'js/Error 'Exception) e#
      ,,,)))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-09 14:53:22

这样做的常见方法是在 key中使用defmacro中的特殊&env绑定。plumatic/schema

代码语言:javascript
复制
(defn cljs-env?
  "Take the &env from a macro, and tell whether we are expanding into cljs."
  [env]
  (boolean (:ns env)))

(defmacro try-catchall
  "A cross-platform variant of try-catch that catches all exceptions.
   Does not (yet) support finally, and does not need or want an exception class."
  [& body]
  (let [try-body (butlast body)
        [catch sym & catch-body :as catch-form] (last body)]
    (assert (= catch 'catch))
    (assert (symbol? sym))
    (if (cljs-env? &env)
      `(try ~@try-body (~'catch js/Object ~sym ~@catch-body))
      `(try ~@try-body (~'catch Throwable ~sym ~@catch-body)))))

用法:

代码语言:javascript
复制
(macros/try-catchall (f)  (catch e# ::exception))
票数 3
EN

Stack Overflow用户

发布于 2017-01-09 05:31:38

您可以重构您的宏以函数调用的形式表示。该函数将接受表单的"thunk“,并将其包装在try中(而不是直接在宏中完成)。

例如:

代码语言:javascript
复制
(defmacro my-macro [& forms]
  `(my-macro* (fn []
                ~@forms)))

然后,您可以将my-macro*定义为:

代码语言:javascript
复制
(defn my-macro* [f]
  (try
    (f)
    (catch #?(:clj Exception :cljs js/Error) e
      ...)))
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41516492

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档