Core.async Helpers
I went to the Boulder Clojurians meetup tonight where we discussed core.async
. One of the topics of discussion was helper functions that help you work with core.async
. I’ve worked with it a few times in the past, and here are a few of the things I seem to do (almost) every time.
Callback to Async
Sometimes, you have a function that is asynchronous via a callback, such as with http-kit.client
, or when working with nodejs
. To convert these functions into channel-based operations can be tedious, so lets just use a function for it!
Imagine a function (f a b callback)
where callback is an (fn [value])
. Let’s create a function (or macro) so we can do (go (<! (cb->async f a b)))
A first cut using a function:
This is a pretty nice tool for working with callback-based functions. But we can make it better! First, we can use async/onto-chan
instead of #(go (>! c %))
. Secondly, we can “inline” the call by using a macro.
Here’s a revised implementation, this time for use with nodejs.
Both these implementations are valid, and the function form is more readable. You can also determine which “put” function is more readable: (onto-chan c [%])
or (go (>! c %))
.
Async as Promise
core.async
provides a lot of functionality for comparatively little syntactical overhead. But it doesn’t always provide helpers for all the use-cases. One case I seem to use a lot (especially in clojurescript) is promises. I like the flexibility of core.async
, but I want more promise-like helpers.
Luckily, the library recently released core.async/promise-chan
, which acts like a promise, containing only ever one value.
Astute observers will note that promise-map
is the promise functor’s fmap function, while then
is the promise monad’s bind function.
Don’t rewrite the wheel
There are so many goodies in the core.async
library that you probably don’t need to write a bunch of generic helper functions.