Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes.
These will be cleaned up during production of the book by copyeditors and proofreaders.
1 Introducing Clojure
This chapter covers:
Clojure as a Lisp
Clojure as a functional programming language
Clojure hosted on the Java Virtual Machine (JVM)
Key features and benefits of Clojure
Any sufficiently complicated C or Fortran program contains an ad hoc, informally specified, bug-ridden, slow implementation of half of Common Lisp.
Philip Greenspun
1.1 Clojure: What and Why?
Clojure is a simple and succinct programming language designed to leverage easily both legacy code and modern multicore processors. Its simplicity comes from a sparse and regular syntax. Its succinctness comes from dynamic typing and functions-as-values (i.e., functional programming). It can easily use existing Java libraries because it is hosted on the Java Virtual Machine. And finally it simplifies multi-threaded programming by using immutable data structures and providing powerful concurrency constructs.
This book covers Clojure version 1.6. In Part one we will learn the fundamentals of Clojure: its syntax, building blocks, data structures, Java interoperability, and concurrency features. In Part two we will see how to use Clojure to solve hard, large-scale, real-world data processing and web programming problems. By the time we are done you will understand why Clojure is traveling a rare path to popularity and how it can transform your approach to developing software.
Clojure's strengths do not lie on a single axis. On the one hand it is designed as a hosted language, taking advantage of the technical strengths of platforms like the Java Virtual Machine, Microsoft's Common Language Runtime, and JavaScript engines on which it runs, while adding the "succinctness, flexibility and productivity" of a dynamically typed language. Clojure's Functional Programming features, including high-performance immutable data structures and a rich set of API's for working with them, result in simpler programs that are easier to test and reason about. Pervasive immutability also plays a central role in Clojure's safe, well-defined concurrency and parallelism constructs. Finally, Clojure's syntax derives from the Lisp tradition, which brings with it an elegant simplicity and powerful metaprogramming tools.
Some of these points may elicit an immediate positive or negative reaction, like whether you have a preference for statically or dynamically typed languages. Other language design decisions may not be entirely clear. What is a functional programming language and is Clojure like other ones I may have seen? Does Clojure also have an object system or provide design abstractions similar to mainstream object-oriented languages? What are the advantages and disadvantages of hosting the language on an existing VM?
The promise of Clojures synthesis of features is a language that is composed of simple, comprehensible parts that not only provide power and flexibility to writing programs, but also liberate your understanding of how the parts of a language can fit together. Let no one deceive you: there are many things to learn. Developing in Clojure requires learning how to read and write Lisp, a willingness to embrace a functional style of programming, and a basic understanding of the Java Virtual Machine (JVM) and its runtime libraries. Well introduce all three of these Clojure pillars in this chapter to arm you for what lies ahead in the rest of the book: a deep dive into an incredible language thats both new and old.
1.1.1 Clojurea modern Lisp
Clojure is a fresh take on Lisp, one of the oldest programming language families still in active use (second only to Fortran). Lisp is not a single, specific language, but rather a style of programming language that was designed in 1958 by Turing award winner John McCarthy. Today the Lisp family consists primarily of Common Lisp, Scheme, and Emacs Lisp, with Clojure as one of the newest additions. Despite its fragmented history, Lisp implementations, including Clojure, are used for cutting-edge software systems in various domains: NASA s Pathfinder mission-planning software, algorithmic trading at hedge funds, flight-delay prediction, data mining, natural language processing, expert systems, bio-informatics, robotics, electronic design automation, web development, next-generation databases and many others.
Clojure belongs to the Lisp family of languages, but does not adhere to any existing implementation exclusively, preferring instead to combine the strengths of several Lisps as well as features from languages like ML and Haskell. Lisp has the reputation of being a dark art, a secret weapon of success, and has been the birthplace of language features like conditionals, automatic garbage collection, macros, and functions as language values (not just procedures or subroutines). Clojure builds on this Lisp tradition with a pragmatic approach to functional programming, a symbiotic relationship with existing runtimes like the JVM, and advanced features like built-in concurrency and parallelism support.
We'll get a practical sense of what it means for Clojure to be a Lisp when we explore its syntax later in this chapter, but before we get bogged down in the details, let's consider the other two pillars of Clojure's design: Clojure as a functional programming language hosted on the JVM.
1.1.2 Clojurepragmatic functional programming
Functional programming (FP) languages have seen an explosion in popularity in the last few years. Languages like Haskell, OCaml, Scala, and F# have risen from obscurity, and existing languages like C/C++, Java, C#, Python, and Ruby have borrowed features popularized by these languages. With all of this activity in the community, it can be difficult to determine what defines a functional programming language.
The minimum requirement to be a functional language is to treat functions as something more than named subroutines for executing blocks of code. Functions in a FP language are values , just like the string "hello" and the number 42 are values. You can pass functions as arguments to other functions, and functions can return functions as output values. If a programming language can treat a function as a value, it is often said to have first-class functions. All of this may sound either impossible or too abstract at this point, so just keep in mind that we're going to see functions used in new, interesting ways in the code examples later in this chapter.
In addition to functions as first-class values, most FP languages also include the following unique features:
Pure functions with referential transparency.
Immutable data structures as the default.
Controlled, explicit changes to state.
These three features are interrelated. Most functions in a FP design are pure , which means they do not have any side effects on the world around them such as changing global state or doing I/O operations. Functions should also be referentially transparent , meaning that if you give the same function the same inputs, it will always return the same output. At the most elementary level, functions that behave this way are simple , and it is simpler and easier to reason about code that behaves consistently, without respect to the implicit environment in which it runs. Making immutable data structures the language default guarantees that functions cannot alter the arguments passed to them and thus makes it much easier to write pure, referentially-transparent functions In a simplistic sense, it is as if arguments are always passed by value and not by reference.