Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Created July 16, 2013 15:21
Show Gist options
  • Save ericnormand/6009721 to your computer and use it in GitHub Desktop.
Save ericnormand/6009721 to your computer and use it in GitHub Desktop.
A macro for turning a function with a callback into an async channel.
(defn sub
[s form]
(cond
(= '<&> form) s
(seq? form) (map (partial sub s) form)
(list? form) (map (partial sub s) form)
(vector? form) (mapv (partial sub s) form)
(map? form) (into {} (for [[k v] form] [(sub s k) (sub s v)]))
(set? form) (into #{} (map (partial sub s) form))
:else form))
(defmacro <&
"Used to convert a non-blocking function with a callback into an async channel.
Returns a channel which will receive the result of the callback.
Usage: (<& function args <&> more-args)
Where <&> is where the callback should be placed."
[& body]
(let [ff (gensym "f")]
`(let [c# (chan)
~ff (fn
([x#] (put! c# x#))
([x# & rst#] (put! c# (cons x# rst#))))]
~(sub ff body)
c#)))
(comment ;; Some examples
(<& + 1 2)
(<& some-fun-with-callback 2 <&>)
(<& .ajax js/jQuery "http://google.com" (clj->js {:success <&>})))
@ericnormand
Copy link
Author

An example macroexpansion of the jquery ajax example above.

(clojure.core/let [c__2758__auto__ (clojure.core.async/chan)
                   f2875 (clojure.core/fn ([x__2759__auto__]
                                            (clojure.core.async/put!
                                              c__2758__auto__
                                              x__2759__auto__))
                           ([x__2759__auto__ & rst__2760__auto__]
                             (clojure.core.async/put!
                               c__2758__auto__
                               (clojure.core/cons
                                 x__2759__auto__
                                 rst__2760__auto__))))]
  (.ajax js/jQuery "http://google.com" (clj->js {:success f2875}))
  c__2758__auto__)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment