About this Book

The only difference between Shakespeare and you was the size of his idiom list—not the size of his vocabulary.

Alan Perlis[6]

6 “Epigrams in Programming,” ACM SIGPLAN Notices 17, no. 9 (September 1982).

Why learn Clojure?

When this book was conceived, our first instinct was to create a comprehensive comparison between Clojure and its host language, Java. After further reflection, we reached the conclusion that such an approach would be disingenuous at best and disastrous at worst. Granted, some points of comparison can’t be avoided, as you’ll see occasionally in this book; but Java is very different from Clojure, and to try to distort one to explain the other would respect neither. Therefore, we decided a better approach would be to focus on “The Clojure Way” of writing code.

When we become familiar with a programming language, the idioms and constructs of that language serve to define the way we think about and solve programming tasks. It’s therefore natural that when faced with an entirely new language, we find comfort in mentally mapping the new language onto the familiar old. But we plead with you to leave all your baggage behind; whether you’re from Java, Common Lisp, Scheme, Lua, C#, or Befunge, we ask you to bear in mind that Clojure is its own language and begs an adherence to its own set of idioms. You’ll discover concepts that you can connect between Clojure and languages you already know, but don’t assume that similar things are entirely the same.

We’ll work hard to guide you through the features and semantics of Clojure to help you build the mental model needed to use the language effectively. Most of the samples in this book are designed to be run in Clojure’s interactive programming environment, commonly known as the Read-Eval-Print Loop (REPL), an extremely powerful environment for experimentation and rapid prototyping.

By the time you’re done with this book, the Clojure Way of thinking about and solving problems will be another comfortable tool in your toolbox. If we succeed, then not only will you be a better Clojure programmer, but you’ll also start seeing your programming language of choice—be it Java, JavaScript, Elixir, Ruby, J, or Python—in an entirely different light. This reassessment of topics that we often take for granted is essential for personal growth.

Who should read this book?

This book isn’t a beginner’s guide to Clojure. We start fast and don’t devote much space to establishing a running Clojure environment, although we do provide some guidance. Additionally, this isn’t a book about Clojure’s implementation details,[7] but instead one about its semantic details. This is also not a “cookbook” for Clojure, but rather a thorough investigation into the ingredients that Clojure provides for creating beautiful software. Often we’ll explain how these ingredients mix and why they make a great match, but you won’t find complete recipes for systems. Our examples directly address the discussion at hand and at times leave exposed wiring for you to extend and thus further your own knowledge. It wouldn’t serve us, you, or Clojure to try to awkwardly mold a comprehensive lesson into the guise of a book-length project. Often, language books spend valuable time halfheartedly explaining “real-world” matters totally unrelated to the language itself, and we wish to avoid this trap. We strongly feel that if we show you the “why” of the language, then you’ll be better prepared to take that knowledge and apply it to your real-world problems. In short, if you’re looking for a book amenable to neophytes that will also show you how to migrate Clojure into existing codebases, connect to NoSQL databases, and explore other “real-world” topics, then we recommend the book Clojure in Action by Amit Rathore (Manning, 2011).

7 Although such a book would be an amazing thing. If you’re interested in such a book, then drop a line to Manning asking us to write one.

Having said all that, we do provide a short introduction to the language and feel that for those of you willing to work hard to understand Clojure, this is indeed the book for you. Further, if you already have a background in Lisp programming, then much of the introductory material will be familiar, thus making this book ideal for you. Additionally, this book is very much a guide on how to write idiomatic Clojure code. We won’t highlight every idiom used, but you can assume that if it’s in this book, it’s the Clojure Way of expressing programs. Although it’s by no means perfect, Clojure has a nice combination of features that fit together into a coherent system for solving programming problems. The way Clojure encourages you to think about problems may be different than you’re used to, requiring a bit of work to “get.” But once you cross that threshold, you too may experience a kind of euphoria, and in this book we’ll help you get there. These are exciting times, and Clojure is the language we hope you’ll agree is an essential tool for navigating into the future.

Roadmap

We’re going to take you on a journey. Perhaps you’ve started on this journey yourself by exploring Clojure beforehand. Perhaps you’re a seasoned Java or Lisp veteran and are coming to Clojure for the first time. Perhaps you’re coming into this book from an entirely different background. In any case, we’re talking to you. This is a self-styled book for the adventurous and will require that you leave your baggage behind and approach the enclosed topics with an open mind. In many ways, Clojure will change the way you view programming, and in other ways it will obliterate your preconceived notions. The language has a lot to say about how software should be designed and implemented, and we’ll touch on these topics one by one throughout this book.

Foundations

Every so often, a programming language comes along that can be considered foundational. Occasionally a language is invented that shakes the foundations of the software industry and dispels the collective preconceived notions of “good software practices.” These foundational programming languages always introduce a novel approach to software development, alleviating if not eliminating the difficult problems of their time. Any list of foundational languages inevitably raises the ire of language proponents who feel their preferences shouldn’t be ignored. But we’re willing to take this risk, and therefore table 1 lists programming languages in this category.

Table 1. Foundational programming languages

Year

Language

Inventor(s)

Interesting reading

1957 Fortran John Backus John Backus, “The History of Fortran I, II, and III,” IEEE Annals of the History of Computing 20, no. 4 (1998).
1958 Lisp John McCarthy Richard P. Gabriel and Guy L. Steele Jr., “The Evolution of Lisp” (1992), www.dreamsongs.com/Files/HOPL2-Uncut.pdf.
1959 COBOL Design by committee Edsger Dijkstra, “EWD 498: How Do We Tell Truths That Might Hurt?” in Selected Writings on Computing: A Personal Perspective (New York: Springer-Verlag, 1982).
1968 Smalltalk Alan Kay Adele Goldberg, Smalltalk-80: The Language and Its Implementation (Reading, MA: Addison-Wesley, 1983).
1972 C Dennis Ritchie Brian W. Kernighan and Dennis M. Ritchie, The C Programming Language (Englewood Cliffs, NJ: Prentice Hall, 1988).
1972 Prolog Alain Colmerauer Ivan Bratko, PROLOG: Programming for Artificial Intelligence (New York: Addison-Wesley, 2000).
1975 Scheme Guy Steele and Gerald Sussman Guy Steele and Gerald Sussman, “The Lambda Papers,” http://mng.bz/sU33.
1983 C++ Bjarne Stroustrup Bjarne Stroustrup, The Design and Evolution of C++ (Reading, MA: Addison-Wesley, 1994).
1986 Erlang Telefonaktiebolaget L. M. Ericsson Joe Armstrong, “A History of Erlang,” Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages (2007).
1987 Perl Larry Wall Larry Wall, Tom Christiansen, and Jon Orwant, Programming Perl (Cambridge, MA: O’Reilly, 2000).
1990 Haskell Simon Peyton Jones Miran Lipovača, “Learn You a Haskell for Great Good!” http://learnyouahaskell.com/.
1995 Java Sun Microsystems David Bank, “The Java Saga,” Wired 3.12 (1995).
2007 Clojure? Rich Hickey You’re reading it.

Like them or not, there’s little dispute that the listed programming languages have greatly influenced the way software is constructed. Whether Clojure should be included in this category remains to be seen, but Clojure does borrow heavily from many of the foundational languages and from other influential programming languages to boot.

Chapter 1 starts our journey and provides some of the core concepts embraced by Clojure. These concepts should be well understood by the time you’ve finished the chapter. Along the way, we’ll show illustrative code samples highlighting the concepts at hand (and sometimes even pretty pictures). Much of what’s contained in chapter 1 can be considered “The Clojure Philosophy,” so if you’ve ever wondered what inspired and constitutes Clojure, we’ll tell you.

Chapter 2 provides a fast introduction to specific features and syntax of Clojure.

Chapter 3 addresses general Clojure programming idioms that aren’t easily categorized. From matters of truthiness and style to considerations of packaging and nil, chapter 3 is a mixed bag but important in its own right.

Data types

The discussion of scalar data types in chapter 4 will be relatively familiar to most programmers, but some important points beg our attention, arising from Clojure’s interesting nature as a functional programming language hosted on the Java Virtual Machine. Java programmers reading this book will recognize the points made concerning numerical precision (section 4.1), and Lisp programmers will recognize the discussion on Lisp-1 versus Lisp-2 (section 4.4). Programmers will appreciate the practical inclusion of regular expressions as first-class syntactical elements (section 4.5). Finally, longtime Clojure programmers may find that the discussion of rationals and keywords (sections 4.2 and 4.3, respectively) sheds new light on these seemingly innocent types. Regardless of your background, chapter 4 provides crucial information for understanding the nature of Clojure’s under-appreciated scalar types.

Clojure’s novel persistent data structures are covered in chapter 5; this should be enlightening to anyone wishing to look more deeply into them. Persistent data structures lie at the heart of Clojure’s programming philosophy and must be understood to fully grasp the implications of Clojure’s design decisions. We’ll only touch briefly on the implementation details of these persistent structures, because they’re less important than understanding why and how to use them.

Functional programming

Chapter 6 deals with the nebulous notions of immutability, persistence, and laziness. We’ll explore Clojure’s use of immutability as the key element in supporting concurrent programming. We’ll likewise show how, in the presence of immutability, many of the problems associated with coordinated state change disappear. Regarding laziness, we’ll explore the ways Clojure uses it to reduce the memory footprint and speed execution times. Finally, we’ll cover the interplay between immutability and laziness. For programmers coming from languages that allow unconstrained mutation and strict evaluation of expressions, chapter 6 may prove to be an initially mind-bending experience. But with this mind-bending comes enlightenment, and you’ll likely never view your preferred programming languages in the same light.

Chapter 7 tackles Clojure’s approach to functional programming full-on. For those of you coming from a functional programming background, much of the chapter will be familiar, although Clojure presents its own unique blend. But like every programming language dubbed “functional,” Clojure’s implementation provides a different lens by which to view your previous experience. For those of you wholly unfamiliar with functional programming techniques, chapter 7 will likely be astonishing. Coming from a language that centers on object hierarchies and imperative programming techniques, the notion of functional programming seems alien. But we believe Clojure’s decision to base its programming model in the functional paradigm to be the correct one, and we hope you’ll agree.

Large-scale design

Clojure can be used as the primary language for any application scale, and the discussion of macros in chapter 8 may change your ideas regarding how to develop software. Clojure as a Lisp embraces macros, and we’ll lead you through the process of understanding them and realizing that with great power comes great responsibility.

In chapter 9, we’ll guide you through the use of Clojure’s built-in mechanisms for combining and relating code and data. From namespaces to multimethods to types and protocols, we’ll explain how Clojure fosters the design and implementation of large-scale applications.

Clojure is built to foster the sane management of program state, which in turn facilitates concurrent programming, as you’ll see in chapter 10. Clojure’s simple yet powerful state model alleviates most of the headaches involved in such complicated tasks, and we’ll show you how and why to use each. Additionally, we’ll address the matters not directly solved by Clojure, such as how to identify and reduce those elements that should be protected using Clojure’s reference types.

Finally, this part of the book concludes with a discussion of Clojure’s support for in-process parallelism in chapter 11.

Host symbiosis

Clojure is a symbiotic programming language, meaning it’s intended to run atop a host environment. For now, the most widely used host is the Java Virtual Machine (JVM), but the future bodes well for ClojureScript, a Clojure implementation targeting JavaScript environments. In any case, Clojure provides top-notch functions and macros for interacting directly with its host platforms. In chapter 12, we’ll discuss the ways Clojure interoperates with the JVM, and in chapter 13 we’ll focus on ClojureScript interop. Chapter 13 also discusses how ClojureScript was implemented in the Clojure Way and is a nice example of sound program design and implementation.

Tangential considerations

The final part of this book discusses topics that are equally important: the design and development of your application viewed through the lens of the Clojure philosophy. In chapter 14, we’ll discuss how Clojure fosters and motivates a data-oriented approach to program design and how such an approach simplifies implementation and testing. After that, we’ll show you ways to improve your application’s performance in single-threaded applications. Clojure provides many mechanisms for improving performance, and we’ll delve into each, including their usage and caveats where applicable, in Chapter 15.

Chapter 16 is a fun chapter in which we explore the growing trend in the Clojure ecosystem to use logic programming techniques to supplement and extend functional programming. This chapter uses the core.logic library to explore “post-functional programming.”

To wrap up the book, in chapter 17, we’ll address the ways that Clojure changes the ways you look at tangential development activities, such as the definition of your application domain language, testing, error-handling, and debugging.

Code conventions

The source code used throughout this book is formatted in a straightforward and pragmatic fashion. Any source code listings inlined within the text—for example, (:lemonade :fugu)—are formatted using a fixed-width font. Source code snippets outlined as blocks of code are offset from the left margin and formatted in a fixed-width font:

(def population {::zombies 2700 ::humans 9})
(def per-capita (/ (population ::zombies) (population ::humans)))
(println per-capita "zombies for every human!")

Whenever a source code snippet indicates the result of an expression, the result is prefixed by the characters ;=>. If the code was added specifically for the second edition of the book, we generally use ;;=> to help you recognize newer code topics. This particular result comment serves a threefold purpose:

  • It helps the result stand out from the code expressions.
  • It indicates a Clojure comment.
  • Because of this, entire code blocks can be easily copied from an E-book or PDF version of this book and pasted into a running Clojure REPL:
    (def population {::zombies 2700 ::humans 9})
    (/ (population ::zombies) (population ::humans))
    ;=> 300

Additionally, any expected display in the REPL that’s not a returned value (such as exceptions or printouts) is denoted with a leading ; prior to the actual return value:

(println population)
; {:user/zombies 2700, :user/humans 9}
;=> nil

In the previous example, the map displayed as {:user/zombies 2700, :user/humans 9} is the printed value, whereas nil denotes the returned value from the println function. If no return value is shown after an expression, you can assume that it’s either nil or negligible to the example at hand.

Reading Clojure code

When you’re reading Clojure code, skim it while reading left to right, paying just enough attention to note important bits of context (defn, binding, let, and so on). When reading from the inside out, pay careful attention to what each expression returns to be passed to the next outer function. This is much easier than trying to remember the entire outer context when reading the innermost expressions.

All code formatted as either inline or block-level is intended to be typed or pasted exactly as written into Clojure source files or a REPL. We generally don’t show the Clojure prompt user> because it will cause copy/paste to fail. Finally, we at times use the ellipsis ... to indicate an elided result or printout.

Code annotations accompany many of the listings, highlighting important concepts. In some cases, numbered bullets link to explanations that follow the listing.

Getting Clojure

If you don’t currently have Clojure, then we recommend you retrieve the Leiningen project-automation tool created by Phil Hagelberg, located at http://leiningen.org/, and install it via the instructions at http://leiningen.org/#install.

The Leiningen REPL

After downloading and installing Leiningen, run the following from your operating system’s console:

lein repl

You may see output from Leiningen indicating installation progress for required libraries, but this is a bootstrapping step needed to run lein for the first time. Once it has completed, you’ll see something like the following:

nREPL server started on port 53337 on host 127.0.0.1
REPL-y 0.2.1
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)

user=>

There is a point to note about the Clojure REPL provided by Leiningen. First, the REPL that lein repl executes is an enhanced version of the base Clojure REPL. In addition to greater error display, the Leiningen REPL provides a fairly nice command-history feature, autocomplete, parenthesis and bracket matching, and command suggestion. For example, if you know the command you wish to use is “update ... something,” you can type update into the REPL and press the Tab key, whereupon you’ll see the following:

user=> (update-
update-in      update-proxy
user=> (update-

The Leiningen REPL shows all functions and named values starting with the text update currently available in the active (in this case, user) namespace.

Now that Leiningen is installed and running, you can start typing code, perhaps from this book. For now, you can try this:

(+ 1 2 3 4 5)

Pressing the Enter key will cause the REPL to evaluate the call to the + function, displaying the result like so:

15
user=>

The REPL is a powerful environment in which to actively test and develop code. Most Lisp and Clojure programmers use a REPL of some sort to develop their code, either directly as shown here or indirectly via another development tool such as Emacs, Eclipse, Vim, Light Table, and so on. If you see a developer writing Lisp code, you better believe that a REPL is close at hand.

A Leiningen project file

The beauty of Leiningen is in the simplicity it provides in creating and managing Clojure project dependencies. It does this by taking a project specification file, usually named project.cl; resolving the dependencies listed in the file; and running any extra tasks, such as compilation, testing, or the like. For example, the project.clj file for the source code in this book is shown and explained in the following listing.

Listing 1. project.clj file for The Joy of Clojure source code

The book won’t proceed under the assumption that you’re an expert in Leiningen, but we’ll mention it from time to time. We recommend reading up on its capabilities, especially if you plan to write Clojure code on a regular basis, because it’s the ubiquitous choice.

Downloading code examples

Source code for all working examples in this book is available for download from the publisher’s website at www.manning.com/TheJoyofClojureSecondEdition. We also maintain an external version at https://github.com/joyofclojure/book-source that we update occasionally.

Author Online

Purchase of The Joy of Clojure, Second Edition includes free access to a private web forum run by Manning Publications where you can make comments about the book, ask technical questions, and receive help from the authors and from other users. To access the forum and subscribe to it, point your web browser to www.manning.com/TheJoyofClojureSecondEdition. This page provides information on how to get on the forum once you are registered, what kind of help is available, and the rules of conduct on the forum.

Manning’s commitment to our readers is to provide a venue where a meaningful dialogue between individual readers and between readers and the authors can take place. It is not a commitment to any specific amount of participation on the part of the authors, whose contribution to the AO remains voluntary (and unpaid). We suggest you try asking the authors some challenging questions lest their interest stray!

The Author Online forum and the archives of previous discussions will be accessible from the publisher’s website as long as the book is in print.

About the authors

MICHAEL FOGUS is a core contributor to Clojure and ClojureScript with experience in distributed simulation, machine vision, and expert system construction.

CHRIS HOUSER is a key contributor to Clojure and ClojureScript who has implemented many of their features.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.170.134