Choosing to learn a new programming language is an investment in time and effort. This blog is to document my forthcoming adventures in learning the
Clojure language.
Reflecting on the process will no doubt help me, and perhaps it will be of use and of interest to those who are considering are already embarking on similar adventures, with Clojure or other languages.
Why Clojure (for me)?
Rich Hickey, designer of Clojure, went looking for "A Lisp, for Functional Programming, symbiotic with an established Platform, designed for Concurrency". Here's an
extended explication of his motivation.
Taking Rich's short version as a jumping off point, here's why I want pretty much those same things.
I want a Lisp for expressive power: I subscribe to the DRY programming maxim:
Don't Repeat Yourself, also known as DIE (Duplication Is Evil). Much (most?) lot of my refactoring is centered around identifying and eliminating duplication. Now, while any given programming language will have idioms that can be used to eliminate
some duplication, when it comes to the grammar and ceremonyof the language, in the absence of meta-programming features, you're stuck. Instead of eliminating duplication, at some level, you end up endlessly repeating yourself!
Lisps, with their Keatsian
code-data duality -- code is data, data is code -- have the most coherent and convenient approach to meta-programming, so I wants me a Lisp. Lisps excel allow -- neigh encourage -- a DSL-construction approach to programming. Although Ruby, Haskell and the ML family have some facilities in this area, and you can do a fair bit in any dynamic language with an
eval statement, the Lisps have the cleanest approaches to meta-programming.
Functional Programming is fun, and powerful! Read
SICP (and do the exercises) to get into it! Programs written in a functional style favor largely immutable data. This jibes well with me given my mathematics background. Things that don't change are
much easier to reason about than things that do. That's why, in the case of the very mutable object-oriented paradigm invariants are so helpful in figuring out what's going on (or going wrong). Pure functions are easier to write tests for than almost everything else, since you don't have to set up or mock out the rest of a larger system.
An established Platform gives the batteries-included effect - access to existing libraries, and portability equal to the underlying platform.
Design for concurrency is a welcome bonus, if not a core criterion of mine. Large scale multi-cores are coming, and the old techniques simply won't stand up. Time to learn...
* * *
Now, of the most prevalent Lisps:
Common Lisp is big and imposing, and I find its Lisp-2-ness a bit kludgey, while
Scheme is far cleaner, but despite spending some time in it, I find myself reverting to Python for day-to-day tasks; anyway I'll return to check out
Racket periodically.
Arc is a ways off, so it will keep.
Clojure, by contrast, features a number of strong pragmatic balances in its design: For example, I particularly like that it is a Lisp-1, like Scheme, but offers a more CL-like approach to macros (although with somewhat better hygiene out-of-the-box).
On the platform front, hopefully Clojure in Clojure will get some traction soon, leading to availability on other platforms besides the JVM: Javascript (hello V8), CLR, and -- at a stretch -- Objective C would be nice too (but I won't hold my breath on that one!).