I made one of my New Year’s resolutions for this year to teach myself Clojure in my spare time. There were a few reasons for this. First, I realized this year that I have been dabbling and/or programming for nearly a decade, with Python as my preferred language throughout that time period.
Python is an unbelievable language. What astounds me even more is that it is still improving. Python 2.x/3 and the entire open source community of library implementors that surround it are bringing more and more useful utilities into the fold of the language. It has stood the test of time in a serious way. It has proven that simpler languages can be better. Personally, it has served as my salvation from the tar pit that is the Java ecosystem.
No scene from prehistory is quite so vivid as that of the mortal struggles of great beasts in tar pits. In the mind’s eye one sees dinosaurs, mammoths, and saberteeth tigers struggling against the grip of the tar. The fiercer the struggle, the more entangling the tar, and no beast is so strong or so skillful but that he ultimately sinks.
Large-system programming has over the past decade been such a tar pit, and many great and powerful beasts have thrashed violently in it. Most have emerged with working systems — few have met goals, schedules, and budgets. Large and small, massive or wiry, team after team has become entangled in the tar. No one thing seems to cause the difficulty — any particular paw can be pulled away. But the accumulation of simultaneous and interacting factors brings slower and slower motion. Everyone seems to have been surprised by the stickiness of the problem, and it is hard to discern the nature of it. But we must try to understand it if we are to solve it.
- Frederick Brooks, The Mythical Man-Month
That said, Python is a language with a specific set of opinions and implementation choices. It is multi-paradigm and supports both functional and object-oriented programming very well. However, the programs that are written in Python tend to be imperative in nature. Declarative approaches to programming are basically unsupported, short of implementing your own DSL atop Python.
As I moved away from Java, that ecosystem saw an explosion of interest in dynamic and functional languages, including JRuby, Jython, Groovy (which I have written about before), Scala, and Clojure.
Clojure seems the most interesting development of all these to me. As I wrote before, Groovy is my “Winston Wolf” for the Java ecosystem — my go-to language for when I am forced to interoperate with Java. But Clojure could possibly return me to Java for some of my programming tasks because of the way it has co-opted the best pieces of the platform and left the rest behind.
Essentially, Clojure has “batteries included”, because it has the Java standard library. Expected utility libraries for data type conversion, data collections, network, disk I/O, dates & times, etc. are all included as part of the standard library. A wealth of open source libraries fill in the other gaps similarly to Python’s community. And Clojure is fast and optimized because it has the JVM. This is described well in Clojure’s Rationale document.
But Clojure, unlike a language like Groovy, is truly a “fresh start”. We have a fast JVM. We have a powerful standard library. But now, let’s write declarative programs. Let’s write programs that are fundamentally unlike the ones we are used to in Python, Ruby, and Java.
I don’t know whether Clojure programs will be better or worse than equivalent Python programs. But I know they will be different. And that is enough to make it a worthwhile exercise for my brain — to see what is possible.
In the tutorial I read on Clojure for Non-Lisp Programmers, the author wrote:
One of the things that takes some getting used to is that Clojure is a functional language. All expressions in Clojure return a value. Often, a single Clojure expression will span several lines, where the C-like programmer would write it out the same logic as a block of code consisting of several distinct statements. The distinct statements may assign a value to a variable to be used in the following statements. Programs written in functional languages tend to have larger statements spanning multiple lines rather than a multiline block of code split into smaller statements. This way of building programs can take some getting used to, but once you’ve learned it, the new way can be just as easy as the old. There are several advantages to writing programs this way.
The final reason I want to learn Clojure is out of historical curiosity. A computer science old-timer I once met and respected told me that if I read the book The Anatomy of Lisp and understood it, I would instantly be a better computer scientist and programmer for it.
After reading the first couple of chapters, I knew exactly what he meant — but also knew that I did not have the background to complete it. I am hoping Clojure’s mix of practicality and purity will allow me to rediscover this dusty corner of computer science history, and open my mind to possibilities that may have been lost in time.
As a first foray into this functional world, I seek to fully understand a simple web application, ring-sample, written by my friend, Andrew Diamond, which he open sourced as a teaching tool for Clojure.