Error handling in cljc macro

It was surprisingly difficult for me to define a macro for error handling in both clj and cljs . I assumed that it was easy to replace Exceptionwith js/Error, but it turned out to be more complicated.

First I tried this:

(defmacro my-macro
  [& forms]
 `(try
    ~@forms
    (catch #?(:clj Exception :cljs js/Error) e#
      ,,,)))

But it caused Exceptionevery time. Soon, I realized that the problem was that the macro was called during compilation of my cljs files that occur in the clj environment . Therefore, I would need to return a macro of the form that would allow the correct exception class at runtime. I tried this:

(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#
      ,,,)))
+4
2

- :ns &env, defmacro. plumatic/schema:

(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)))))

:

(macros/try-catchall (f)  (catch e# ::exception))
+2

, . "thunk" try ( , ).

:

(defmacro my-macro [& forms]
  `(my-macro* (fn []
                ~@forms)))

my-macro* :

(defn my-macro* [f]
  (try
    (f)
    (catch #?(:clj Exception :cljs js/Error) e
      ...)))
+1

Source: https://habr.com/ru/post/1666057/


All Articles