Pure Danger Tech


navigation
home

Clojure Hills of Abstraction

02 Sep 2011

Fogus had a post today about the Scala “Cliff of Insanity” and Java’s “Cliff of Inanity”. I requested in the comments his Clojure curve for comparison and he instead threw down the gauntlet requesting my own take on it.

Thus I present the rolling Clojure hills of abstraction:

There is an initial learning phase of Clojure which I have called “deprogramming” where you must unlearn the unwise practices of your previous language (presuming it’s most likely Java or some other stateful imperative language). Personally, I was pretty familiar with Scheme and some FP when I started Clojure so I did not find this to be much of an issue.

There was a comment on Fogus’s entry that Clojure was daunting because of its syntax. Bah, that’s ridiculous. There is virtually no syntax (although there is more than your average Lisp).

Almost everything you need to know:

  1. expressions are surrounded by parentheses with the operator/function in prefix position: (foo arg arg)
  2. literal syntaxes for the core Clojure collections: lists (), vectors [], maps {}, sets #{}
  3. keywords and symbols are namespaced (a.b/c) but keywords start with a :
  4. anonymous function sugar – #( … % …)
  5. destructuring syntax
  6. misc other punctuation: comment ;, regex #””, meta ^, dereferencing @, var quote #’, ignore #_, etc
  7. macro stuff like `, ~, ~@, etc

(Note: I am including things here like destructuring that are maybe not technically syntax but are so pervasive and reused that they may as well be.) I think you can easily grok #1-4 within an hour. You can skip the rest for a while and learn them as you come across them but I think destructuring is the only one that you really need to read most other Clojure code (barring macros).

After the Deprogramming, there is a long period of writing clever functions, then discovering that there are even more cleverer ways to implement them, and in fact they already exist in the Clojure API. I think it took me a couple months of regular use with the Clojure [Fogus had a post today about the Scala “Cliff of Insanity” and Java’s “Cliff of Inanity”. I requested in the comments his Clojure curve for comparison and he instead threw down the gauntlet requesting my own take on it.

Thus I present the rolling Clojure hills of abstraction:

There is an initial learning phase of Clojure which I have called “deprogramming” where you must unlearn the unwise practices of your previous language (presuming it’s most likely Java or some other stateful imperative language). Personally, I was pretty familiar with Scheme and some FP when I started Clojure so I did not find this to be much of an issue.

There was a comment on Fogus’s entry that Clojure was daunting because of its syntax. Bah, that’s ridiculous. There is virtually no syntax (although there is more than your average Lisp).

Almost everything you need to know:

  1. expressions are surrounded by parentheses with the operator/function in prefix position: (foo arg arg)
  2. literal syntaxes for the core Clojure collections: lists (), vectors [], maps {}, sets #{}
  3. keywords and symbols are namespaced (a.b/c) but keywords start with a :
  4. anonymous function sugar – #( … % …)
  5. destructuring syntax
  6. misc other punctuation: comment ;, regex #””, meta ^, dereferencing @, var quote #’, ignore #_, etc
  7. macro stuff like `, ~, ~@, etc

(Note: I am including things here like destructuring that are maybe not technically syntax but are so pervasive and reused that they may as well be.) I think you can easily grok #1-4 within an hour. You can skip the rest for a while and learn them as you come across them but I think destructuring is the only one that you really need to read most other Clojure code (barring macros).

After the Deprogramming, there is a long period of writing clever functions, then discovering that there are even more cleverer ways to implement them, and in fact they already exist in the Clojure API. I think it took me a couple months of regular use with the Clojure](http://clojure.org/cheatsheet) tacked to my monitor before I had a reasonable idea what already existed there and which tool to grab when I needed it.

After that, I found there were just a series of new challenges, each of which I needed to learn a new abstraction provided in Clojure. I didn’t use any of the state/concurrency facilities in Clojure for the first four months or so that I used it. When I did, I read up on refs, atoms, agents, STM, etc and then was able to use them. When I needed to write some macros, I learned how they worked and then started using them (still learning lots on those). When I needed dispatch flexibility, I learned about multimethods and protocols. When I needed types, I learned about deftype and defrecord. I call these the Clojure Hills of Abstraction. :)

The key here is that Clojure is great at making abstractions and Clojure has a wonderful set of core abstractions that are *largely orthogonal*. That allows you to add knowledge about each new tool when it’s useful to learn it and ignore it other than that.

I’d be curious to hear what experience others have had while learning Clojure… I personally found it easier to learn than Scala or Ruby or Groovy.