Over a million developers have joined DZone.

gofor it

DZone's Guide to

gofor it

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

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:

  [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 tochannel 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.

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.


Published at DZone with permission of David Pollak. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}