1
votes

Usually functions that may fail return nil: some-> macro is designed to chain computations like that (looks like that "M" word). The question is how to use this approach with core.async, like park for heavy async/thread computation which can fail and cannot return nil because of channels restriction on this. Is {:right/:left} maps idiomatic? Any good practices that you use?

1
You mean you take a value off the chan, and want to react to whether or not the taken value represents a failed action? If you don't need to handle a failure, you could just not put in the first place. I seem to recall in a toy project declaring a namespaced keyword, and checking against that when taking. That single keyword represented failure, and was namespaced to prevent accidental false positives. Left/right isn't really an idiom in Clojure, or at least not one I've come across in my couple years dealing with it. - Carcigenicate
@Carcigenicate i have to handle the failure. So, keywords, as usual - fevgenym
Yes. Keywords are the hammer for many problems, for better or worse. - Carcigenicate
A fun, useful exercise might be creating a ->while-not macro that threads the expressions while the return value of the forms isn't a certain value. It would be like a generalized some->. You could redefine some-> using it with something like (defmacro some-> [expr & forms] `(->while-not nil ~expr ~@forms)) - Carcigenicate

1 Answers

0
votes

You can do something similar to this using the with-exception-default macro from the Tupelo library. It allows you to replace an exception with any arbitrary value, which could be a "sentinal" value to indicate (in a non-exception way) that a failure occurred (such as putting a keyword on a core.async channel):

  (let [good (with-exception-default :failed (+ 2 3))
        bad  (with-exception-default :failed (/ 2 0)) ] ... )

good => 5
bad  => :failed

Another approach is to just wrap regular thread -> with a test:

(or (-> ...<forms>...)  ; assumes `false` cannot be a result
  :failed)