Clojure Gazette 1.30
Issue 1.30 - February 04, 2013
Man, I love Clojure. People have called me a fanboy before. But can't someone just like something? I just like it! I like tomatoes. Does that make me a tomato fanboy?
Clojure does not feel like hacking. It feels like a very analytical precision surgery of a problem into its component parts. You can write big, ugly Clojure. But good Clojure is readable and maintainable, and a pleasure to write in.
The two libraries and accompanying presentations I have included in this issue highlight some of the things I like about Clojure. Please check them out.
I have also been working on that Clojure-related project I mentioned last time. It will be coming soon! And here's a hint: it will help people learn Clojure.
**Eric Normand **
PS. I love to hear from you. Just hit reply!
In one sentence: Graph is a simple, declarative, creatively named way to express system composition.
Someone recently said on Twitter (paraphrasing) that abstraction in Clojure shortens your code but in Java abstraction lengthens your code. Graph is a great example of Clojure's power to peel apart a problem into decomposable abstractions.
Graph encapsulates many things that I like about Clojure. Graph is declarative, it is data-driven, and it exactly models one aspect of an existing problem.
"Declarative", of course, is a relative term. But in this case, what I mean by "declarative" is that an important aspect of the program is explicitly represented in code, allowing for manipulations at a more abstract level. For instance, in C, functions are declarative compared to ad hoc assembly subroutine calls. In Graph, data dependencies, which are typically only inferred in code, are made explicit. Because you can express the data dependencies abstractly, Graph allows you to compile the dependency graphs using different evaluation strategies. The video shows three different evaluation strategies: eager, lazy, and parallel. Lisp programmers have been doing this kind of thing for years.
Data-driven is related, but describes a different aspect. Data-driven is also a relative, nebulous term. Imagine a function which had a large conditional expression with many cases. Each case tests for equality to some value, and if it succeeds, runs some code. Of course, you can write the code this way, but it would not be data-driven. To make it data-driven, you would need to represent the tests and the code that runs on success in a data structure. For example, you can make the equality test value the key in a map, and the code to run a function as the value of the map. By converting the code into data, you open it up to manipulation by the features in the programming language.Graph is data-driven because a Graph is an actual Clojure hash map. It can be created as a literal and transformed using normal Clojure functions which act on hash maps. The data in the hash map defines the Graph and the "compiler" operates on that data.
Modeling problems is a tough affair. Ostensibly, all programming is modeling. But, as we all know, we can build knit models of castles or we can build Lego models of castles. If you want to change the knit castle, you have to un-knit quite a lot. And when you un-knit it, it's just a thread of yarn. With Lego, though, you might have to disassemble the castle a bit, but the pieces you have can be easily recombined. Graph is a single type of Lego block that can be used to build castles, space stations, or houses. Graph addresses the very well-defined problem of decomposing large functions into smaller, interdependent components. The problem is not just well-defined. It is also very common. I looked through an existing codebase of mine and found a couple of examples where Graph would fit perfectly.
If you would like to use Graph, find it on the Github.
Conrad Barski presents some exciting ideas in this presentation. He shows some libraries that do what Clojure does best: cleaning up other people's abstractions! Specifically, by using ClojureScript, his Webfui library cleans up the browser's abstractions of events, the DOM, and AJAX.
Barski shows how DOM Events can be made more functional by converting them from an object representing a change to a value showing the old DOM element and the new DOM element. This small change unifies the event model with the DOM model. You only have to understand the HTML (in this case, Hiccup) model of the page and the previous state is preserved (since it is immutable).
The DOM is cleaned up in two ways. First, in Webfui, you are operating on a pseudo-DOM which is just an atom with hiccup data structures. You get all of the concurrency guarantees and watch features of Clojure atoms. Second, Webfui cleans up the differences between HTML attributes and CSS pseudo-classes. :active and :hover classes are now available in the same way as HTML attributes! It also allows for normal DOM properties which are not available in HTML (scrolltop, height, width) to be accessible in the same way.
AJAX is cleaned up by being explicit about what values are unknown in the client-side code. A watch function runs when a value becomes unknown, makes an AJAX request, and replaces the value when the AJAX request completes. I like this idea because it explicitly represents unknown values which need to be fetched from the server. Normally, I think of AJAX requests as procedural. When there's a value I need from the server, I show a loading spinner, make the request, and when it completes, replace the loading spinner with a representation of the data returned. However, Barski proposes a much better model: the renderer is simply a function from state to HTML that knows how to display unknown values (spinner) and known values. Some other system deals with fetching.
Webfui and this presentation are packed with lots of great ideas. Check it out on the Github.