A Lazy Sequence

A couple of lists

From Python to Clojure.

In the last post I talked about factors that have caused myself and others to look around for languages to move on to from Python. I noted that a number of languages that expat pythonistas are looking at are more recent entries in the Functional Programming space. After dabbling in a number of languages over the last two years I have settled on Clojure. This post examines the tradeoffs from my perspective.

When I first came to Python it was around 2002. With a background in Java from university Python provided an appealing language to get things done. As a quick summary:

The big obvious tradeoff was speed but, as has been noted many times by many people, this isn't a huge impediment for a large class of programs. Not so obvious is the GIL and the problems it brings to multi-threaded programs but I don't want to go into that debate here.

Another problem that comes to the surface after extended use is packaging third party library code. Tools like virtualenv and pip etc have helped a lot in recent years, but its certainly not Python's strength.

I've had the chance to work on some really cool projects with Python. I built a skinnable, scriptable media player with webservice integration for my internship, extracted a nice little parser combinator library from this site with some friends, I worked on a Django based financial application full time and a many more small projects.

Any language I move to has to feel as expressive as the experience I get with Python (sans learning curve difficulty). This brings us to Clojure.

I've been following Clojure since mid 2008, dabbling in it and writing little toy applications. The functional style has been appealing to me more and more. So what features does Clojure bring to the table for me?

One obvious lack for Clojure is (native) libraries that are as comprehensive as some of the ones for Python. There isn't a web framework that competes with Django in terms of feature set and breadth for example. The language is very young (just over 2 years) and it is developing rapidly, but you might still find yourself building (or wrapping java) what you could have got from the toolbox in Python.

Secondly, if Object Orientation is key to how you design code, you will be out of luck. Same goes for JVM: If you have no love for the JVM platform, Clojure won't be the right choice for you.

There is a lot of overlap between the two lists. Neither list covers all the great things about either language, just the things that spring to mind about why I like each.

So what makes Clojure more appealing than other Functional (or Hybrid OO/FP) languages? One key differentiator is that as a pragmatically designed language, IO and state considerations are clearly part of the plan. Not only this, the role of state, identity and time with regard to concurrency has been considered throughout the language's and core library's design.

Unlike Python (and other contemporaries like Java), Clojure does not provide mutability or identity to all data or variables. Instead, data is immutable, and the core data-structures are designed with that in mind. Secondly explicit reference types are provided. The programmer is expected to write core logic in a pure functionally mode where possible, and then use the reference types to maintain identity where needed. This will be familiar to anybody who has seen the buzz around functional programming and concurrency. Unlike in the C family, where pointers merely address memory, each reference type provides additional semantics. These semantics allow Clojure to provide managed statefulness; this is analogous to managed memory. A lot has been written about Clojure's concurrency features, and by smarter people than me, so I won't say any more.

One consideration with the current state of Clojure is that the planned 1.2 release is bringing two new constructs: Types and Protocols. These correspond roughly to Classes and Interfaces in Java. The current release (1.1) provides a Structs feature that uses dynamic maps as types, but this feature is due to be deprecated with 1.2. This places new users in an awkward position, but is a necessary change and will only be good in the long run.

The features that made Python a great choice in 2002 are no longer just the domain of so called 'Scripting' languages. Switching to Clojure does have trade-offs but it feels like the right choice for me.

Postscript

“Show Us The Code!” I'm not going to for this post. Snippets could be manufactured in situations that show each language as 'better'. If you would like to see a small piece of Clojure written by a relative beginner, check out Caponia. This is an ultra light weight, in memory, full text index library that Matt and I designed during lunch and he implemented over the following day.

In contrast to this rather fluffy post, the next two will be looking at state and evaluation semantics in Clojure, chock full of code snippets. Update: The first half is now up.

See also

  1. These days its excellent with the ctypes library
  2. No doubt Common Lisp has good reasons for how it does things, but from the outside its opaque and frankly not as nice as Clojure. Clearly a subjective judgement, but I'm allowed to make those when I'm evaluating a language for my own use.
8 February 2010