Motivations

It all started with John McCarthy, the year 1958, and a small language named Lisp. Why are we, five decades later, discussing a sudden springing-to-life of incarnations of this programming language predated only by Fortran? It turns out that Lisp never really died. It was merely in hibernation all those years, "pining for the fjords" of the Java Virtual Machine, powerful CPUs, and abundant RAM. That day has arrived. In fact, the multi-core architecture and ever-harder concurrency problems computer science is currently aiming to solve are a perfect fit for a Lisp dialect. Rich Hickey realized this and began work on a language we now know as Clojure.

In just a few short years, the Java Virtual Machine (JVM) has gone from a platform solely running the Java language, to becoming the preferred platform for the execution of hundreds of cutting edge programming languages. Some of these languages, such as Groovy, Scala and Clojure are vying for the community's respect as the most innovative language on the Java Virtual Machine. Let's explore why Clojure is one of those frontrunners and why it deserves a place in the tool belt of any leading edge JVM developer.

Don't let yourself think Clojure is only for the elite, or for solving a narrow class of programming problems. It is a general-purpose dynamic language of the JVM, appropriate for a broad variety of tasks by any developer willing to learn a few potentially unfamiliar—but accessible—concepts.

Why the Strange Syntax?

Lisps are often ridiculed as having a plethora of parenthesis, but they serve a very useful purpose. They reduce all ambiguity and require no lengthy set of evaluation precedence rules; deepest parens execute first. For the benefit of the developer, the frequency of parentheses in Clojure were engineered down to the barest minimum Lisp has ever seen.

Clojure's simple syntax rules are a direct benefit of the code being a direct version of the abstract syntax tree (AST). Following the execution of the code becomes a matter of traversing that tree, which is often a simple recursion to the deepest pair of parentheses, then proceeds outward. For example, Figure 1 shows a basic math problem's Clojure syntax and evaluation.

Section 2

Language Foundations

Code Is Data

The fact that Clojure's unconventional syntax asks you to type in the AST directly has a surprising implication: namely, that all Clojure code is data. In fact, there is no formal distinction between code and data in Clojure. When code is represented in text files, it exists as a set of nested forms (or S-expressions). When these forms are parsed by the reader (which is like a part of the compiler), they become Clojure data structures, no different in kind than the data structures you create yourself in Clojure code.

We call this property homoiconicity. In a homoiconic language, code and data are the same kind of thing. This is very different from a language like Java, in which variables and the code that manipulates them live in two separate conceptual spaces.

As a result of Clojure's homoiconicity, every Clojure program is a data structure, and every Clojure data structure can potentially be interpreted as a program. The data structure that is the program is available for the program to modify at run time. This arguably allows for the most powerful metaprogramming possible in any language.

Data Types...?

Since all Clojure code is a Clojure data structure, we don't speak of data types and data structures the way we do in a conventional language. Instead, we speak of forms. Forms are text strings processed by the Clojure Reader.

Form Name

Description

Examples

String

A string of characters, implemented by java.lang.String.

"angry monkey", "Mutable state considered harmful"

Number

A numeric literal that evaluates to itself.

6.023E23, 42

Ratio

A rational number.

22/7, 1/3, 24/601

Boolean

A boolean literal form. False and nil evaluate to false; true and everything else evaluate to true. Also returned by predicate functions.

true, false

Character

A single character literal, implemented by java.lang.Character.

\z, \3, \space, \tab, \ newline, \return

Nil

The null value in Clojure.

nil

Keyword

A form beginning with a colon that evaluates to itself. Also a function that looks itself up in a map.

:deposed, :royalty

Symbol

A name that refers to something. Symbols may be function names, data, Java class names, and namespaces.

str-join, java.lang. Thread, clojure.core, +, *source-path*

Set

A collection of unique elements. Also a function that looks up its own elements.

#{:bright :copper :kettles}, #{135713}

Map

A collection of key/value pairs. Note that commas are optional. Also a function that looks up its own keys.

{:species "monkey" :emotion "angry"}, {"A" 23, "B" 83}

Vector

An ordered collection with high-performance indexing semantics. Also a function that looks up an element by its position.

[112358]

List

An ordered collection, also known as an S-expression, or sexp. The fundamental data structure of Clojure. When the list is not quoted, the first element is interpreted as a function name, and is invoked.

'(13 17 19 23), (map str [13 17 19 23])

Note that all Clojure data structures are immutable, even things like maps and lists that we normally think of as mutable. Any time you perform an operation on a data structure to change it, you are actually creating a whole new structure in memory that has the modification. If this seems horribly inefficient, don't worry; Clojure represents data structures internally such that it can create modified views of immutable data structures in a performant way.

Mutability in Clojure

Clojure invites you to take a slightly different view of variables from the imperative languages you are used to. Conceptually, Clojure separates identity from value. An identity is a logical entity that has a stable definition over time, and can be represented by one of the reference types (ref, agent, and atom). An identity "points to" a value, which by contrast is always immutable. We could bind a name to a value as follows—this is analogous to assignment in Java—but there is no idiomatic way to change the value had by that name:

In the example above, 42 is the value bound to the name universal-answer. If we wanted the universal answer to be able to change, we might use an atom:

=> (def universal-answer (atom "what do you get when you multiply six by nine"))
#'user/universal-answer
=> (deref universal-answer)
"what do you get when you multiply six by nine"

Note that we access the value of an atom using the deref function. To change the value pointed to by an atom, we must be explicit. For example, to change the universal answer to be a function instead of a number or a string, we use the reset! function:

The double parentheses around the deref call are necessary because the value of universal-answer is a function. Wrapping that function in parentheses causes Clojure to evaluate it, returning the value 54. Note that the number, the string, and the function above are values, and do not change. The symbol universal-answer is an identity, and changes its value over time.

In traditional concurrent programming, synchronizing access to shared variables is the limiting factor in creating correct programs, and is an intellectually daunting task besides. Clojure provides an elegant solution in its reference types. In addition to refs, we have atoms and agents for concurrently managing mutable state. Together these three types form a significantly improved abstraction over traditional threading and synchronization. You can read more about them here: http://clojure.org/refs, http://clojure.org/atoms, http://clojure.org/agents.

Sequences

Clojure's Aggregate forms (i.e., String, Map, Vector, List, and Set) can all be interpreted as sequences, or simply "seqs" (pronounced seeks). A seq is an immutable collection on which we can perform three basic operations:

first: returns the first item in the sequence

=> (first [2 7 1 8 2 8 1 8 2 8 4 5 9 0])
2

rest: returns a new sequence containing all elements except the first

=> (rest [2 7 1 8 2 8 1 8 2 8 4 5 9 0])
(7 1 8 2 8 1 8 2 8 4 5 9 0)

cons: returns a new sequence containing a new element added to the beginning

=> (cons 2 [7 1 8 2 8 1 8 2 8 4 5 9 0])
(2 7 1 8 2 8 1 8 2 8 4 5 9 0)

These three functions form the backbone of seq functionality, but there is a rich library of additional seq functions in clojure.core.

Clojure sequences can be infinite, like the set of all positive integers:

=> (def positive-integers (iterate inc 1))

Since this sequence would take infinite memory to realize, Clojure provides the concept of a lazy sequence. Lazy sequences are only evaluated when they are needed at run time. If we tried to print the sequence of all primes, we would need infinite memory and time:

Of course, lazy sequences are not magical. They will require enough memory and computation to generate the values we request, but they defer that computation until needed, and usually don't attempt eager computation of the entire sequence.

Section 3

REPLs

Running a REPL

A standard tool for experimenting with Clojure is a Read Eval Print Loop, or REPL. It is an interactive prompt that remembers the results of previous operations and allows you to use those results in future statements.

A Web REPL

If getting a REPL up and running seems like too much effort for a first encounter with Clojure, try "Lord of the REPLs", a Google App Engine Web application that immediately lets you try out snippets of syntax. (http://lotrepls.appspot.com/)

Note that in some execution environments, it is necessary to first import the repl-utils functions before calling source. Leiningen and the standard Clojure 1.2 repl have the source function available automatically.

(use 'clojure.contrib.repl-utils)

Tooling

All the major development tools have Clojure plug-ins bringing both syntax highlighting and a REPL to the table.

Eclipse

IntelliJ

NetBeans

Function Catalog

The sheer volume of functions available in Clojure can be overwhelming. However, a combination of ClojureDocs.org and docstring referencing can aid in finding one that fits a specific need. Here are a few excerpts of frequently used functions:

Interoperability

Many new languages are being developed and hosted on the JVM for its robust deployment model, excellent performance characteristics, and rich ecosystem. These languages take different approaches to interoperating with and embracing the Java tradition they inherit. For its otherwise alien syntax, Clojure has surprisingly clean Java interop, and this is no accident. The decision to host Clojure on the JVM was not merely an implementation detail; rather, the JVM is a first- class part of Clojure's world. Significant language features were added to cooperate cleanly with the JVM. Clojure's Java interop is implemented without intrusive and abstraction- leaking wrappers, but instead by direct programming of Java objects in Clojure code.

Open Source Tools & Frameworks

Leiningen

The JVM has many build tools such as Maven, Gradle and Ant that are compatible with Clojure. However, Clojure has its own build tool that is "designed to not set your hair on fire." Setting it up proves that this goal has been achieved.

The Clojure Ecosystem

Clojure is more than just an experiment to bring Lisp to the JVM. It is a growing component of production applications, often focusing on exciting new frontiers of parallel, graph navigation, and scalable computing.

Stories abound of Clojure in use at telecommunications firms, analytics agencies, and social media companies. The following short list can be of use in convincing colleagues that the language is worth investigating for applicability to challenging problem domains.

Bookmarks

Clojure is still in its formative stages and new resources are popping up all the time. One of the best ways to keep up with the additions to its ecosystem is through a hand-crafted list of bookmarks about this new JVM language.

About the Author

Tim Berglund combines a broad perspective on software architecture and team dynamics with a passion for hands-on development. He specializes in web development using the Grails framework, bringing expertise in the browser, database design, and enterprise integration to bear on browser-based solutions. His skill as a teacher and his integrative approach to technology, team, and organizational problem-solving makes him an ideal partner during periods of disruptive technology change in your organization.

Tim embraces the Java platform, including both the Java language and its high- productivity cousin, Groovy. He also helps clients bring agility to their database development using the Liquibase database refactoring tool, having applied, coached, and lectured on it extensively. He is committed to applying and helping teams excel with agile methods in all of his engagements.

Through his partnership with ThirstyHead.com, Tim offers public and private classroom training in Groovy, Grails, and Liquibase, and is available to develop custom courseware by private engagement.

Tim is a frequent speaker at domestic and international conferences, including the Scandinavian Developer Conference, JavaZone, Strange Loop, and the No Fluff Just Stuff tour.

Matthew McCullough is an energetic 15 year veteran of enterprise software development, open source education, and co-founder of Ambient Ideas, LLC, a Denver, Colorado, USA consultancy. Matthew is a published author, open source creator, speaker at over 100 conferences, and author of three of the top 10 Refcardz of all time. He writes frequently on software and presenting at his blog: http://ambientideas.com/blog.

Section 9

Recommended Book

If you're a Java programmer, if you care about concurrency, or if you enjoy working in low-ceremony language such as Ruby or Python, Programming Clojure is for you. Clojure is a general- purpose language with direct support for Java, a modern Lisp dialect, and support in both the language and data structures for functional programming. Programming Clojure shows you how to write applications that have the beauty and elegance of a good scripting language, the power and reach of the JVM, and a modern, concurrency-safe functional style. Now you can write beautiful code that runs fast and scales well.