4

I keep seeing this macro <?, in swanodette's code which looks really useful :

In this gist :

;; BOOM!!! we can convert async errors into exceptions
(go (try
      (let [x (<? (run-task (.-readFile fs) "foo.txt" "utf8"))]
        (.log js/console "Success" x))
      (catch js/Error e
        (.log js/console "Oops" e))))

In this blog post :

(go (try
      (let [tweets    (<? (get-tweets-for "swannodette"))
            first-url (<? (expand-url (first (parse-urls tweets))))
            response  (<? (http-get first-url))]
        (. js/console (log "Most recent link text:" response)))
      (catch js/Error e
        (. js/console (error "Error with the twitterverse:" e)))))

<? is just a touch of macro sugar that expands into something like (throw-err (<! [expr])). In core.async <! serves the same purpose as ES6's yield operator. If an asynchronous process writes an error onto its channel we will convert it into an exception.

But I can't find a definition for it. How is it implemented in Clojure{Script} ?

2
  • 1
    FYI: All his code is on github: github.com/swannodette/swannodette.github.com File you're looking for: macros.clj & helpers.cljs Commented Aug 22, 2015 at 19:10
  • @Andre thanks ! I was looking for that ! (Searching <? on github doesn't work) Commented Aug 22, 2015 at 22:14

1 Answer 1

2

Alright so here is what I am using so far. There is probably room for improvement.

In Clojure :

(defn throw-err [e]
  (when (instance? Throwable e) (throw e))
  e)

(defmacro <? [ch]
  `(throw-err (<! ~ch)))

In ClojureScript :

(defn error? [x]
  (instance? js/Error x))


(defn throw-err [e]
  (when (error? e) (throw e))
  e)

(defmacro <? [ch]
  `(throw-err (<! ~ch)))

I am completely unsure about the readability of my solution though (throw-err looks like it should throw an error, but it doesn't. At least not every time).

Sign up to request clarification or add additional context in comments.

3 Comments

Exceptions inside worker threads don't necessarily do anything to let you know they happened. Stuart Sierra has a good blog post showing some settings you can establish to ensure you actually see errors in the world of async. "In the JVM, when an exception is thrown on a thread other than the main thread, and nothing is there to catch it, nothing happens. The thread dies silently."
Is it necessary for <? to be a macro?
Answering my own question, yes, it can't be a function, because <! must be inside a go block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.