All Clojure code is made up of expressions, each of which
evaluates to a single value. This is in contrast to many languages that
rely upon valueless statements—such as
continue—to control program flow
imperatively. Clojure’s corollaries to these statements are all
expressions that evaluate to a value.
You’ve already seen a few examples of expressions in Clojure:
[60 80 100 400]
(average [60 80 100
(+ 1 2)
These expressions all evaluate to a single value. The rules for that evaluation are extraordinarily simple compared to other languages:
Lists (denoted by parentheses) are calls, where the first value in the list is the operator and the rest of the values are parameters. The first element in a list is often referred to as being in function position (as that’s where one provides the function or symbol naming the function to be called). Call expressions evaluate to the value returned by the call.
Symbols (such as
+) evaluate to the named value in
the current scope—which can be a function, a named local like
numbers in our
average function, a Java class, a macro, or
a special form. We’ll learn about macros and special forms in a little
bit; for now, just think of them as functions.
All other expressions evaluate to the literal values they describe.
Lists in Lisps are often called s-expressions
or sexprs—short for symbolic
expressions due to the significance of symbols in
identifying the values to be used in calls denoted by such lists.
Generally, valid s-expressions
that can be successfully evaluated are often referred to as
then else) is an
[60 80 100 400] is a vector form. Not
all s-expressions are forms:
(1 2 3)
is a valid s-expression—a list of three integers—but evaluating it will
produce an error because the first value in the list is an integer,
which is not callable.
The second and third points are roughly equivalent to most other languages (although Clojure’s literals are more expressive, as we’ll see shortly). However, an examination of how calls work in other languages quickly reveals the complexity of their syntax.
Table 1-1. Comparison of call syntax between Clojure, Java, Python, and Ruby
|Clojure expression||Java equivalent||Python equivalent||Ruby equivalent|
[a] In-place increment and decrement operations have no direct corollary in Clojure, because unfettered mutability isn’t available. See Chapter 2, particularly On the Importance of Values for a complete discussion of why this is a good thing.
[b] Remember, even forms that influence control flow in
Clojure evaluate to values just like any other expression,
Notice that call syntax is all over the map (we’re picking on Java here the most, but Python and Ruby aren’t so different):
Infix operators are available (e.g.,
al instanceof List),
but any nontrivial code ends up having to use often-significant
numbers of parentheses to override default precedence rules and make
evaluation order explicit.
Instance method calls use an unusual variety of infix positions, where the
target of the method (which will be assigned to
this within the body of the method being
called) is specified first, with the formal parameters to the method
coming after the method name.
In contrast, Clojure call expressions follow one simple rule: the first value in a list is the operator, the remainder are parameters to that operator. There are no call expressions that use infix or postfix position, and there are no difficult-to-remember precedence rules. This simplification helps make Clojure’s syntax very easy to learn and internalize, and helps make Clojure code very easy to read.
 Python uses the same sort of infix position for its instance
methods, but varies from Algol-family brethren by requiring that
methods explicitly name their first parameter, usually