gofor it July 22, 2014
The gofor
macro
I've started working on a series of open source library code for Clojure called Dragonmark that roughly falls into three categories: utilities, a distributed CSP library, and a sample web app that demonstrates distributed CSP.
So, why?
Mostly, I think that the semantics for interprocess communication should be the same as the semantics for local communication. Clojure's core.async library provides a really nice set of APIs to communicate asynchronously, have backpressure, and in general "do the right thing."
But core.async does not provide any interprocess communication. In fact, nothing in Clojure-land does a good job of abstracting the transport layer and maintaining the semantics of core.async.
So, Dragonmark.
Making core.async
less verbose
If you're going to do core.async right, there's a pattern... create a channel to receive a reply, send a message, wait for a timeout or an answer, close the channel, if the answer came from the channel, do something, else, do an error.
Using Scala and LAFuture
is really easy in a for
comprehension. I wanted something similar in Clojure-land,
so I wrote the gofor
macro.
Here's an example:
(gofor
[a (foo channel {:thing value :other_thing other_value})]
:let [b (+ a 1)]
[c (baz other_channel)
d (moose third_channel {:p b}
:timeout 45000]
(println a b c)
:error (println &err &at))
The [a (foo channel {:thing value :other_thing other_value})]
sends a message to channel
with {:_cmd "foo" :thing value :other_thing other_value :_return a_created_channel}
and waits up to 30 seconds for an answer. If the answer doesn't arrive, the :error
code is invoked
and the comprehension is terminated. If the answer does come back, it's bound to a
.
Next, we bind b
to (a + 1)
.
Next, we kick off a parallel set of messages to other_channel
and third_channel
and wait up to
45 seconds for a response.
If we succeed, the (println a b c)
code is executed.
It's a first pass at something that makes core.async
more usable, especially
in the case of cross-address space messaging where timeouts and failures should
be expected and embraced.