Вы находитесь на странице: 1из 63

Clojure - Functional Programming for the JVM

Introduction
The goal of this article is to provide a fairly comprehensive introduction to the Clojure programming language. A large number of features are covered, each in a fairly brief manner. Feel free to skip around to the sections of most interest. The section names in the table of contents are hyperlinks to make this easier when reading on-line. lease send feedback on errors and ways to improve e!planations to mark"ociweb.com, or fork the repository and send a pull-re#uest. $%m especially interested in feedback such as&

'ou said (, but the correct thing to say is '. 'ou said (, but it would be more clear if you said '. 'ou didn%t discuss ( and $ think it is an important topic.

)pdates to this article that indicate the *last updated* date and provide a dated list of changes will be provided at http&++www.ociweb.com+mark+clojure+. Also see my article on software transactional memory and the Clojure implementation of it at http&++www.ociweb.com+mark+stm+. Code e!amples in this article often show the return value of a function call or its output in a line comment ,begins with a semicolon- followed by *-.* and the result. For e!ample&
(+ 1 2) ; showing return value -> 3 (println "Hello") ; return value is nil, showing output -> Hello

Functional Programming
Functional programming is a style of programming that emphasi/es *first-class* functions that are *pure*. $t was inspired by ideas from the lambda calculus. * ure functions* are functions that always return the same result when passed the same arguments, as opposed to depending on state that can change with time. This makes them much easier to understand, debug and test. They have no side effects such as changing global state or performing any kind of $+0, including file $+0 and database updates. 1tate is maintained in the values of function parameters saved on the stack ,often placed there by recursive calls- rather than in global variables saved on the heap. This allows functions to be e!ecuted repeatedly without affecting global state ,an important characteristic to consider when transactions are discussed later-. $t also opens the door for smart compilers to improve performance by automatically reordering and paralleli/ing code, although the latter is not yet common. $n practice, applications need to have some side effects. 1imon eyton-2ones, a major contributor to the functional programming language 3askell, said the following& *$n the end, any program must manipulate state. A program that has no side effects whatsoever is a kind of black bo!. All you can tell is that the bo! gets hotter.* ,http&++oscon.blip.tv+file+456789:

The key is to limit side effects, clearly identify them, and avoid scattering them throughout the code. ;anguages that support *first-class functions* allow functions to be held in variables, passed to other functions and returned from them. The ability to return a function supports selection of behavior to be e!ecuted later. Functions that accept other functions as arguments are called *higher-order functions*. $n a sense, their operation is configured by the functions that are passed to them. The functions passed in can be e!ecuted any number of times, including not at all. <ata in functional programming languages is typically immutable. This allows data to be accessed concurrently from multiple threads without locking. There%s no need to lock data that can%t be changed. =ith multicore processors becoming prevalent, this simplification of programming for concurrency is perhaps the biggest benefit of functional programming. $f all of this sounds intriguing and you%re ready to try functional programming, be prepared for a si/able learning curve. >any claim that functional programming isn%t more difficult than object-oriented programming, it%s just different. Taking the time to learn this style of programming is a worthwhile investment in order to obtain the benefits described above. opular functional programming languages include Clojure, Common ;isp, ?rlang, F@, 3askell, >;, 0Caml, 1cheme and 1cala. Clojure and 1cala were written to run on the 2ava Airtual >achine ,2A>-. 0ther functional programming languages that have implementations that run on the 2A> include& Armed Bear Common ;isp ,ABC;-, 0Caml-2ava and Cawa ,1cheme-.

Clojure Overview
Clojure is a dynamically-typed, functional programming language that runs on the 2A> ,2ava D or greater- and provides interoperability with 2ava. A major goal of the language is to make it easier to implement applications that access data from multiple threads ,concurrency-. Clojure is pronounced the same as the word *closure*. The creator of the language, Eich 3ickey, e!plains the name this way& *$ wanted to involve C ,C@-, ; ,;isp- and 2 ,2ava-. 0nce $ came up with Clojure, given the pun on closure, the available domains and vast emptiness of the googlespace, it was an easy decision.* Clojure is also available for the .F?T platform. ClojureC;E is an implementation of Clojure that runs on the >icrosoft Common ;anguage Euntime instead of the 2A>. 1ee https&++github.com+clojure+clojure-clr. $n 2uly 5G::, Clojure1cript was announced. $t compiles Clojure code to 2ava1cript. 1ee https&++github.com+clojure+clojurescript. Clojure is an open source language released under the ?clipse ublic ;icense v :.G ,? ;-. This is a very liberal license. 1ee http&++www.eclipse.org+legal+eplfa#.php for more information.

Eunning on the 2A> provides portability, stability, performance and security. $t also provides access to a wealth of e!isting 2ava libraries supporting functionality including file $+0, multithreading, database access, H)$s, web applications, and much more. ?ach *operation* in Clojure is implemented as either a function, macro or special form. Fearly all functions and macros are implemented in Clojure source code. The differences between functions and macros are e!plained later. 1pecial forms are recogni/ed by the Clojure compiler and not implemented in Clojure source code. There are a relatively small number of special forms and new ones cannot be implemented. They include catch, def, do, dot ,%.%-, finally, fn, if, let, loop, monitor-enter, monitor-e!it, new, #uote, recur, setI, throw, try and var. Clojure provides many functions that make it easy to operate on *se#uences* which are logical views of collections. >any things can be treated as se#uences. These include 2ava collections, Clojure-specific collections, strings, streams, directory structures and (>; trees. Few instances of Clojure collections can be created from e!isting ones in an efficient manner because they are persistent data structures. Clojure provides three ways of safely sharing mutable data, all of which use mutable references to immutable data. Eefs provide synchronous access to multiple pieces of shared data ,*coordinated*- by using 1oftware Transactional >emory ,1T>-. Atoms provide synchronous access to a single piece of shared data. Agents provide asynchronous access to a single piece of shared data. These are discussed in more detail in the *Eeference Types* section. Clojure is a ;isp dialect. 3owever, it makes some departures from older ;isps. For e!ample, older ;isps use the car function to get the first item in a list. Clojure calls this first as does Common ;isp. For a list of other differences, see http&++clojure.org+lisps. ;isp has a synta! that many people love ... and many people hate, mainly due to its use of parentheses and prefi! notation. $f you tend toward the latter camp, consider these facts. >any te!t editors and $<?s highlight matching parentheses, so it isn%t necessary to count them in order to ensure they are balanced. Clojure function calls are less noisy than 2ava method calls. A 2ava method call looks like this&
metho !ame(arg1, arg2, arg3);

A Clojure function call looks like this&


(function-name arg1 arg2 arg3)

The open paren moves to the front and the commas and semicolon disappear. This synta! is referred to as a *form*. There is simple beauty in the fact that everything in ;isp has this form. Fote that the naming convention in Clojure is to use all lowercase with hyphens separating words in multi-word names, unlike the 2ava convention of using camelcase. <efining functions is similarly less noisy in Clojure. The Clojure println function adds a space between the output from each of its arguments. To avoid this, pass the same arguments to the str function and pass its result to println .

"" #ava pu$lic voi hello(%tring name) & %'stem(out(println("Hello, " + name); ) ; *lo+ure ( efn hello ,name(println "Hello," name))

Clojure makes heavy use of la/y evaluation. This allows functions to be invoked only when their result is needed. *;a/y se#uences* are collections of results that are not computed until needed. This supports the efficient creation of infinite collections. Clojure code is processed in three phases& read-time, compile-time and run-time. At read-time the Eeader reads source code and converts it to a data structure, mostly a list of lists of lists. At compile-time this data structure is converted to 2ava bytecode. At run-time the bytecode is e!ecuted. Functions are only invoked at run-time. >acros are special constructs whose invocation looks similar to that of functions, but are e!panded into new Clojure code at compile-time. $s Clojure code hard to understandJ $magine if every time you read 2ava source code and encountered synta! elements like if statements, for loops, and anonymous classes, you had to pause and pu//le over what they mean. There are certain things that must be obvious to a person who wants to be a productive 2ava developer. ;ikewise there are parts of Clojure synta! that must be obvious for one to efficiently read and understand code. ?!amples include being comfortable with the use of let, appl', map, filter, re uce and anonymous functions ... all of which are described later.

Getting Started
Clojure code for your own library and application projects will typically reside in its own directory ,named after the project- and will be managed by the ;einingen project management tool. ;einingen ,or *lein* for short- will take care of downloading Clojure for you and making it available to your projects. To start using Clojure, you don%t need to install Clojure, nor deal with jar files or the +ava command K just install and use lein ,instructions on the ;einingen homepage, linked to above-. 0nce you%ve installed lein, create a trivial project to start playing around with&
c ."temp lein new m'-pro+ c m'-pro+ lein repl / starts up the interactive 0123

To create a new application project, do *lein new app m'-app* For more about getting started, see http&++dev.clojure.org+display+doc+HettingL1tarted.

Clojure Syntax
;isp dialects have a very simple, some would say beautiful, synta!. <ata and code have the same representation, lists of lists that can be represented in memory #uite naturally as a tree. 6

is a call to a function named a with arguments $ and c. To make this data instead of code, the list needs to be #uoted. 4(a $ c) or (5uote (a $ c)) is a list of the values a, $ and c. That%s it e!cept for some special cases. The number of special cases there are depends on the dialect.
(a $ c)

The special cases are seen by some as syntactic sugar. The more of them there are, the shorter certain kinds of code become and the more readers of the code have to learn and remember. $t%s a tricky balance. >any of them have an e#uivalent function name that can be used instead. $%ll leave it to you to decide if Clojure has too much or too little syntactic sugar. The table below briefly describes each of the special cases encountered in Clojure code. These will be described in more detail later. <on%t try to understand everything in the table now. Purpose comment character literal ,uses 2ava char typestring ,uses 2ava %tring objects; text

Sugar for line comments


6char 6ta$ 6newline 6space 6uunicode-hex-value

Function macro for block comments


(comment text) (char ascii-code) (char 6uunicode(str char1 char2 ((()

"text"

concatenates characters and many other kinds of values to create a string.


(8e'wor "name")

keywordM an interned stringM keywords with the same name refer 7name to the same objectM often used for map keys keyword resolved in the current namespace regular e!pression
77name /"pattern"

none
(re-pattern pattern)

#uoting rules differ from function form

treated as whitespaceM sometimes , ,a commaused in collections to aid readability list - a linked list vector - similar to an array set map add metadata to a symbol or collection
4(items)

F+A
(list items)

doesn%t evaluate items


,items/&items)

evaluates items
(vector items) (hash-set items) (sorte -set items) (hash-map key-valuepairs) (sorte -map key-valuepairs) (with-meta object metadata-map)

creates a hash set


&key-value-pairs)

creates a hash map


9&key-value-pairs) object

processed at read-time

processed at run-time

get metadata map from a symbol or collection gather a variable number of arguments in a function parameter list
: name

(meta object)

F+A F+A
(new class-name args)

conventional name given to ; ,an underscorefunction parameters that aren%t used construct a 2ava objectM (class-name( args) note the period after the class name call a 2ava method
(( class-or-instance method-name args) or ((method-name classor-instance args)

none

call several 2ava methods, threading the result from each into the ne!t as its first argumentM ((( class-or-object (method1 args) each method can have additional (method2 args) ((() arguments specified inside the parensM note the double period create an anonymous function dereference a Eef, Atom or Agent get >ar object instead of the value of a symbol ,var-#uotesynta! #uote ,used in macrosun#uote ,used in macrosun#uote splicing ,used in macrosauto-gensym ,used in macros to generate a uni#ue symbol name-

none

/(single-expression) ,arg-namesuse < ,same as <1-, <1, <2 (fn expressions)

and so on for arguments


=ref /4name ? .value .=value prefix/

( eref ref) (var name)

none
(un5uote value)

none
(gens'm prefix@)

;isp dialects use prefi! notation rather than the typical infi! notation used by most programming languages for binary operators such as + and A. For e!ample, in 2ava one might write a + $ + c, whereas in a ;isp dialect this becomes (+ a $ c). 0ne benefit of this notation is that any number of arguments can be specified without repeating the operator. Binary operators from other languages are ;isp functions that aren%t restricted to two operands. 0ne reason ;isp code contains more parentheses than code in other languages is that it also uses them where languages like 2ava use curly braces. For e!ample, the statements in a 2ava method are inside curly braces, whereas the e!pressions in a ;isp function are inside the function definition which is surrounded by parentheses. Compare the following snippets of 2ava and Clojure code that each define a simple function and invoke it. The output from both is *edray* and *orangeay*. 9

"" Bhis is #ava co e( pu$lic class 2ig3atin & pu$lic static %tring pig3atin(%tring wor ) & char first3etter C wor (charDt(E); if ("aeiou"(in eFGf(first3etter) HC -1) return wor return wor (su$string(1) + first3etter + "a'"; ) pu$lic static voi main(%tring args,-) & %'stem(out(println(pig3atin("re ")); %'stem(out(println(pig3atin("orange")); ) Bhis is *lo+ure co e( Ihen a set is use as a function, it returns the argument if it is in the set an nil otherwise( Ihen use in a $oolean conteFt, that in icates whether the argument is in the set( ef vowel@ (set "aeiou"))

+ "a'";

) ; ; ; ; (

( efn pig-latin ,wor - ; efines a function ; wor is eFpecte to $e a string ; which can $e treate li8e a se5uence of characters( (let ,first-letter (first wor )- ; assigns a local $in ing (if (vowel@ first-letter) (str wor "a'") ; then part of if (str (su$s wor 1) first-letter "a'")))) ; else part of if (println (pig-latin "re ")) (println (pig-latin "orange"))

Clojure supports all the common data types such as booleans ,with literal values of true and false-, integers, decimals, characters ,see *character literal* in the table above- and strings. $t also supports ratios which retain a numerator and denominator so numeric precision is not lost when they are used in calculations. 1ymbols are used to name things. These names are scoped in a namespace, either one that is specified or the default namespace. 1ymbols evaluate to their value. To access the %'m$ol object itself, it must be #uoted. Ceywords begin with a colon and are used as uni#ue identifiers. ?!amples include keys in maps and enumerated values ,such as 7re , 7green and 7$lue-. $t is possible in Clojure, as it is in any programming language, to write code that is difficult to understand. Following a few guidelines can make a big difference. =rite short, well-focused functions to make them easier to read, test and reuse. )se the *e!tract method* refactoring pattern often. <eeply nested function calls can be hard to read. ;imit this nesting where possible, often by using let to break complicated e!pressions into several less complicated e!pressions. assing anonymous functions to named functions is common. 3owever, avoid passing anonymous functions to other anonymous functions because such code is difficult to read.

REPL
E? ; stands for read-eval-print loop. This is a standard tool in ;isp dialects that allows a user to enter e!pressions, have them read and evaluated, and have their result printed. $t is a very useful tool for testing and gaining an understanding of code. To start a E? ;, enter *lein repl* at a command prompt. This will display a prompt of *userC>*. The part before *C>* indicates the current default namespace. Forms entered after this prompt are evaluated and their result is output. 3ere%s a sample E? ; session that shows both input and output.
userC> ( ef n 2) /4user"n userC> (A n 3) J

is a special form that doesn%t evaluate its first argument, but instead uses the literal value as a name. $ts E? ; output shows that a symbol named *n* in the namespace *user* was defined.
ef

To view documentation for a function, macro or namespace, enter ( oc name). $f it is a macro, the word *>acro* will appear on a line by itself immediately after its parameter list. The item for which documentation is being re#uested must already be loaded ,see the re#uire function-. For e!ample&
(re5uire 4clo+ure(string) ( oc clo+ure(string"+oin) ; -> ; ------------------------; clo+ure(string"+oin ; (,coll- ,separator coll-) ; 0eturns a string of all elements in coll, as returne ; separate $' an optional separator(

$' (se5 coll),

To find documentation on all functions+macros whose name or documentation string contains a given string, enter (fin - oc "text"). To see the source for a function+macro, enter (source name). source is a macro defined in the clo+ure(repl namespace which is automatically loaded in the E? ; environment. To load and e!ecute the forms in a source file, enter (loa -file "file-path"). Typically these files have a (cl+ e!tension. To e!it the E? ; under =indows, type ctrl-/ followed by the enter key or just ctrl-c. To e!it the E? ; on every other platform ,including )F$(, ;inu! and >ac 01 (-, type ctrl-d.

Vars
Clojure provides bindings to Aars, which are containers bound to mutable storage locations. There are global bindings, thread-local bindings, bindings that are local to a function, and bindings that are local to a given form.

Function parameters are bound to Aars that are local to the function. The ef special form binds a value to a symbol. $t provides a mechanism to define metadata, 7 'namic, which allows a thread-local value within the scope of a $in ing call. $n other words, it allows re-definition of assigned value per e!ecution thread and scope. $f the Aar is not re-assigned to a new value in a separate e!ecution thread, the Aar refers to the value of the root binding, if accessed from another thread. The let special form creates bindings to Aars that are bound to the scope within the statement. $ts first argument is a vector containing name+e!pression pairs. The e!pressions are evaluated in order and their results are assigned to the names on their left. These Aars can be used in the binding of other Aars declared within the vector. The e!pressions following the Aar declaration vector contain the Aar,s- that are e!ecuted only within the let scope. Aars within functions that are called within let but defined outside of that scope are not affected by the declarations in the let%s vector. The $in ing macro is similar to let, but it gives new, thread-local values to e!isting global bindings throughout the scope%s thread of e!ecution. The values of Aars bound within the let vector argument are also used in functions, if they use the same Aar names, called from inside that scope. =hen the e!ecution thread leaves the $in ing macro%s scope, the global Aar bindings revert to their previous values. 1tarting in Clojure :.4, binding can only do this for vars declared 7 'namic. Aars intended to be bound to new, thread-local values using $in ing have their own naming convention. These symbols have names that begin and end with an asterisk. ?!amples that appear in this article include Acomman -line-argsA, AagentA, AerrA, Aflush-onnewlineA, AinA, Aloa -testsA, AnsA, AoutA, Aprint-lengthA, Aprint-levelA and Astac8-trace- epthA. Functions that use these bindings are affected by their values. For e!ample, binding a new value to AoutA changes the output destination of the println function. The following code demonstrates usage of ef, efn, let, $in ing, and println.
( ef 97 'namic v 1) ; v is a glo$al $in ing ( efn f1 ,(println "f17 v7" v)) ( efn f2 ,(println "f27 $efore let v7" v) ; creates local $in ing v that sha ows glo$al one (let ,v 2; local $in ing onl' within this let statement (println "f27 in let, v7" v) (f1)) ; outsi e of this let, v refers to glo$al $in ing (println "f27 after let v7" v)) ( efn f3 ,(println "f37 $efore $in ing v7" v) ; same glo$al $in ing with new, temporar' value ($in ing ,v 3; glo$al $in ing, new value

(println "f37 within $in ing function v7 " v) (f1)) ; calling f1 with new value to v ; outsi e of $in ing v refers to first glo$al value (println "f37 after $in ing v7" v)) ( efn fK ,( ef v K)) ; changes the value of v in the glo$al scope (println "(C v 1) C> " (C v 1)) (println "*alling f27 ") (f2) (println) (println "*alling f37 ") (f3) (println) (println "*alling fK7 ") (fK) (println "after calling fK, v C" v)

To run the code above, save it in a file named *vars.clj* and use the shell script for e!ecuting Clojure files described earlier as follows&
L cl+ vars(cl+

The output produced by the code above follows&


; (C v 1) C> true *alling f2 f27 $efore let v7 1 f27 in let, v7 2 f17 v7 1 f27 after let v7 1 *alling f3 f37 $efore $in ing v7 1 f37 within $in ing function v7 f17 v7 3 f37 after $in ing v7 1 *alling fK after calling fK, v7 K

Recap:
Fotice in the first call to f5, the let function%s binding to v did not change its originally declared value, as is shown in the call to f: within the let statement. The value of v in f: is :, not 5. Fe!t, inside f4 within the scope of the $in ing call, the value of v was re-assigned within f: since f: was called within the e!ecution thread of $in ing call%s scope. 0nce f4%s function e!ecution thread e!its from the $in ing call, v is bound to the initially declared binding, :. =hen f6 is called, the binding of v is not within the conte!t of a new e!ecution thread so v is bound to the new value, 6, in the global scope. Eemember that changing a global value is not necessarily a best practice. $t is presented in f6%s definition for demonstration purposes.

:G

Collections
Clojure provides the collection types list, vector, set and map. Clojure can also use any of the 2ava collection classes, but this is not typically done because the Clojure variety are a much better fit for functional programming. The Clojure collection types have characteristics that differ from 2ava%s collection types. All of them are immutable, heterogeneous and persistent. Being immutable means that their contents cannot be changed. Being heterogeneous means that they can hold any kind of object. Being persistent means that old versions of them are preserved when new versions are created. Clojure does this in a very efficient manner where new versions share memory with old versions. For e!ample, a new version of a map containing thousands of key+value pairs where just one value needs to be modified can be created #uickly and consumes very little additional memory. There are many core functions that operate on all kinds of collections ... far too many to describe here. A small subset of them are described ne!t using vectors. Ceep in mind that since Clojure collections are immutable, there are no functions that modify them. $nstead, there are many functions that use the magic of persistent data structures to efficiently create new collections from e!isting ones. Also, some functions that operate on a collection ,for e!ample, a vector- return a collection of a different type ,for e!ample, a 3aM'%e5- that has different characteristics. =AEF$FH& This section presents information about Clojure collections that is important to learn. 3owever, it drones on a bit, presenting function after function for operating on various types of collections. 1hould drowsiness set in, please skip ahead to the sections that follow and return to this section later. The count function returns the number of items in any collection. For e!ample&
(count ,1N "'ellow" true-) ; -> 3

The con+ function, short for conjoin, adds one or more items to a collection. =here they are added depends on the type of the collection. This is e!plained in the information on specific collection types below. The reverse function returns a se#uence of the items in the collection in reverse order.
(reverse ,2 K O-) ; -> (O K 2)

The map function applies a given function that takes one parameter to each item in a collection, returning a la/y se#uence of the results. $t can also apply functions that take more than one parameter if a collection is supplied for each argument. $f those collections contain different numbers of items, the items used from each will be those at the beginning up to the number of items in the smallest collection. For e!ample&
; Bhe neFt line uses an anon'mous function that a s 3 to its argument( (map /(+ < 3) ,2 K O-) ; -> (P O 1E) (map + ,2 K O- ,P J- ,1 2 3 K-) ; a s correspon ing items -> (Q 12)

::

The appl' function returns the result of a given function when all the items in a given collection are used as arguments. For e!ample&
(appl' + ,2 K O-); -> 13

There are many functions that retrieve a single item from a collection. For e!ample&
( ef stooges ,"Roe" "3arr'" "*url'" "%hemp"-) (first stooges) ; -> "Roe" (secon stooges) ; -> "3arr'" (last stooges) ; -> "%hemp" (nth stooges 2) ; in eFes start at E -> "*url'"

There are many functions that retrieve several items from a collection. For e!ample&
(neFt stooges) ; -> ("3arr'" "*url'" "%hemp") ($utlast stooges) ; -> ("Roe" "3arr'" "*url'") ( rop-last 2 stooges) ; -> ("Roe" "3arr'") ; Set names containing more than three characters( (filter /(> (count <) 3) stooges) ; -> ("3arr'" "*url'" "%hemp") (nthneFt stooges 2) ; -> ("*url'" "%hemp")

There are several predicate functions that test the items in a collection and have a boolean result. These *short-circuit* so they only evaluate as many items as necessary to determine their result. For e!ample&
(ever'@ /(instance@ %tring <) stooges) ; -> true (not-ever'@ /(instance@ %tring <) stooges) ; -> false (some /(instance@ !um$er <) stooges) ; -> nil (not-an'@ /(instance@ !um$er <) stooges) ; -> true

Lists
;ists are ordered collections of items. They are ideal when new items will be added to or removed from the front ,constant-time-. They are not efficient ,linear time- for finding items by inde! ,using nth- and there is no efficient way to change items by inde!. 3ere are some ways to create a list that all have the same result&
( ef stooges (list "Roe" "3arr'" "*url'")) ( ef stooges (5uote ("Roe" "3arr'" "*url'"))) ( ef stooges 4("Roe" "3arr'" "*url'"))

The some function can be used to determine if a collection contains a given item. $t takes a predicate function and a collection. =hile it may seem tedious to need to specify a predicate function in order to test for the e!istence of a single item, it is somewhat intentional to discourage this usage. 1earching a list for a single item is a linear operation. )sing a set instead of a list is more efficient and easier. Fevertheless, it can be done as follows&
(some /(C < "Roe") stooges) ; -> true (some /(C < "Rar8") stooges) ; -> nil ; Dnother approach is to create a set from the list ; an then use the contains@ function on the set as follows( (contains@ (set stooges) "Roe") ; -> true

:5

Both the con+ and cons functions create a new list that contains additional items added to the front. The remove function creates a new list containing only the items for which a predicate function returns false. For e!ample&
( ef more-stooges (con+ stooges "%hemp")) ; -> ("%hemp" "Roe" "3arr'" "*url'") ( ef less-stooges (remove /(C < "*url'") more-stooges)) ; -> ("%hemp" "Roe" "3arr'")

The into function creates a new list that contains all the items in two lists. For e!ample&
( ef 8i s-of-mi8e 4("Sreg" "2eter" "To$$'")) ( ef 8i s-of-carol 4("Rarcia" "#an" "*in '")) ( ef $ra '-$unch (into 8i s-of-mi8e 8i s-of-carol)) (println $ra '-$unch) ; -> (*in ' #an Rarcia Sreg 2eter To$$')

The pee8 and pop functions can be used to treat a list as a stack. They operate on the beginning or head of the list.

Vectors
Aectors are also ordered collections of items. They are ideal when new items will be added to or removed from the back ,constant-time-. This means that using con+ is more efficient than cons for adding items. They are efficient ,constant time- for finding ,using nth- or changing ,using assoc- items by inde!. Function definitions specify their parameter list using a vector. 3ere are some ways to create a vector&
( ef stooges (vector "Roe" "3arr'" "*url'")) ( ef stooges ,"Roe" "3arr'" "*url'"-)

)nless the list characteristic of being more efficient at adding to or removing from the front is significant for a given use, vectors are typically preferred over lists. This is mainly due to the vector synta! of ,(((- being a bit more appealing than the list synta! of 4((((). $t doesn%t have the possibility of being confused with a call to a function, macro or special form. The get function retrieves an item from a vector by inde!. As shown later, it also retrieves a value from a map by key. $nde!es start from /ero. The get function is similar to the nth function. Both take an optional value to be returned if the inde! is out of range. $f this is not supplied and the inde! is out of range, get returns nil and nth throws an e!ception. For e!ample&
(get stooges 1 "un8nown") ; -> "3arr'" (get stooges 3 "un8nown") ; -> "un8nown"

The assoc function operates on vectors and maps. =hen applied to a vector, it creates a new vector where the item specified by an inde! is replaced. $f the inde! is e#ual to the number of items in the vector, a new item is added to the end. $f it is greater than the number of items in the vector, an Un eFGutGfToun s1Fception is thrown. For e!ample&
(assoc stooges 2 "%hemp") ; -> ,"Roe" "3arr'" "%hemp"-

:4

The su$vec function returns a new vector that is a subset of an e!isting one that retains the order of the items. $t takes a vector, a start inde! and an optional end inde!. $f the end inde! is omitted, the subset runs to the end. The new vector shares the structure of the original one. All the code e!amples provided above for lists also work for vectors. The pee8 and pop functions also work with vectors, but operate on the end or tail rather than the beginning or head as they do for lists. The con+ function creates a new vector that contains an additional item added to the back. The cons function creates a new vector that contains an additional item added to the front.

Sets
1ets are collections of uni#ue items. They are preferred over lists and vectors when duplicates are not allowed and items do not need to be maintained in the order in which they were added. Clojure supports two kinds of sets, unsorted and sorted. $f the items being added to a sorted set can%t be compared to each other, a *lass*ast1Fception is thrown. 3ere are some ways to create a set&
( ef stooges (hash-set "Roe" "3arr'" "*url'")) ; not sorte ( ef stooges /&"Roe" "3arr'" "*url'")) ; same as previous ( ef stooges (sorte -set "Roe" "3arr'" "*url'"))

The contains@ function operates on sets and maps. =hen used on a set, it determines whether the set contains a given item. This is much simpler than using the some function which is needed to test this with a list or vector. For e!ample&
(contains@ stooges "Roe") ; -> true (contains@ stooges "Rar8") ; -> false

1ets can be used as functions of their items. =hen used in this way, they return the item or nil. This provides an even more compact way to test whether a set contains a given item. For e!ample&
(stooges "Roe") ; -> "Roe" (stooges "Rar8") ; -> nil (println (if (stooges person) "stooge" "regular person"))

The con+ and into functions demonstrated above with lists also work with sets. The location where the items are added is only defined for sorted sets. The is+ function creates a new set where one or more items are removed. For e!ample&
( ef more-stooges (con+ stooges "%hemp")) ; -> /&"Roe" "3arr'" "*url'" "%hemp") ( ef less-stooges ( is+ more-stooges "*url'")) ; -> /&"Roe" "3arr'" "%hemp")

Also consider the functions in the clo+ure(set namespace which include& ifference, in eF, intersection, +oin, map-invert, pro+ect, rename, rename-8e's, select and union. 1ome of these functions operate on maps instead of sets.

:6

Maps
>aps store associations between keys and their corresponding values where both can be any kind of object. 0ften keywords are used for map keys. ?ntries can be stored in such a way that the pairs can be #uickly retrieved in sorted order based on their keys. 3ere are some ways to create maps that store associations from popsicle colors to their flavors where the keys and values are both keywords. The commas aid readability. They are optional and are treated as whitespace.
( ef popsicle-map (hash-map 7re 7cherr', 7green 7apple, 7purple 7grape)) ( ef popsicle-map &7re 7cherr', 7green 7apple, 7purple 7grape)) ; same as previous ( ef popsicle-map (sorte -map 7re 7cherr', 7green 7apple, 7purple 7grape))

>aps can be used as functions of their keys. Also, in some cases keys can be used as functions of maps. For e!ample, keyword keys can, but string and integer keys cannot. The following are all valid ways to get the flavor of green popsicles, which is 7apple&
(get popsicle-map 7green) (popsicle-map 7green) (7green popsicle-map)

The contains@ function operates on sets and maps. =hen used on a map, it determines whether the map contains a given key. The 8e's function returns a se#uence containing all the keys in a given map. The vals function returns a se#uence containing all the values in a given map. For e!ample&
(contains@ popsicle-map 7green) ; -> true (8e's popsicle-map) ; -> (7re 7green 7purple) (vals popsicle-map) ; -> (7cherr' 7apple 7grape)

The assoc function operates on maps and vectors. =hen applied to a map, it creates a new map where any number of key+value pairs are added. Aalues for e!isting keys are replaced by new values. For e!ample&
(assoc popsicle-map 7green 7lime 7$lue 7$lue$err') ; -> &7$lue 7$lue$err', 7green 7lime, 7purple 7grape, 7re 7cherr')

The issoc function takes a map and any number of keys. $t returns a new map where those keys are removed. 1pecified keys that aren%t in the map are ignored. For e!ample&
( issoc popsicle-map 7green 7$lue) ; -> &7purple 7grape, 7re 7cherr')

=hen used in the conte!t of a se#uence, maps are treated like a se#uence of clo+ure(lang(Rap1ntr' objects. This can be combined with the use of dose# and destructuring, both of which are described in more detail later, to easily iterate through all the keys and values. The following e!ample iterates through all the key+value pairs in popsiclemap and binds the key to color and the value to flavor. The name function returns the string name of a keyword.

:D

( ose5 ,,color flavor- popsicle-map(println (str "Bhe flavor of " (name color) " popsicles is " (name flavor) "(")))

The output produced by the code above follows&


Bhe flavor of green popsicles is apple( Bhe flavor of purple popsicles is grape( Bhe flavor of re popsicles is cherr'(

The select-8e's function takes a map and a se#uence of keys. $t returns a new map where only those keys are in the map. 1pecified keys that aren%t in the map are ignored. For e!ample&
(select-8e's popsicle-map ,7re 7cherr') 7green 7$lue-) ; -> &7green 7apple, 7re

The con+ function adds all the key+value pairs from one map to another. $f any keys in the source map already e!ist in the target map, the target map values are replaced by the corresponding source map values. Aalues in maps can be maps, and they can be nested to any depth. Eetrieving nested values is easy. ;ikewise, creating new maps where nested values are modified is easy. To demonstrate this we%ll create a map that describes a person. $t has a key whose value describes their address using a map. $t also has a key whose value describes their employer which has its own address map.
( ef person & 7name "Rar8 >ol8mann" 7a ress & 7street "JKK Slen %ummit" 7cit' "%t( *harles" 7state "Rissouri" 7Mip J33EK) 7emplo'er & 7name "G$+ect *omputing, Unc(" 7a ress & 7street "121KE Ioo crest 1Fecutive Vrive, %uite 2PE" 7cit' "*reve *oeur" 7state "Rissouri" 7Mip J31K1))))

The get-in function takes a map and a key se#uence. $t returns the value of the nested map key at the end of the se#uence. The -> macro and the re uce function can also be used for this purpose. All of these are demonstrated below to retrieve the employer city which is *Creve Coeur*.
(get-in person ,7emplo'er 7a ress 7cit'-) (-> person 7emplo'er 7a ress 7cit') ; eFplaine $elow (re uce get person ,7emplo'er 7a ress 7cit'-) ; eFplaine

$elow

The -> macro, referred to as the *thread* macro, calls a series of functions, passing the result of each as an argument to the ne!t. For e!ample the following lines have the same result&

:9

(f1 (f2 (f3 F))) (-> F f3 f2 f1)

There is also a -@> macro in the clo+ure(core(incu$ator namespace that stops and returns nil if any function in the chain returns nil. This avoids getting a !ull2ointer1Fception. The re uce function takes a function of two arguments, an optional value and a collection. $t begins by calling the function with either the value and the first item in the collection or the first two items in the collection if the value is omitted. $t then calls the function repeatedly with the previous function result and the ne!t item in the collection until every item in the collection has been processed. This function is the same as in+ect in Euby and fol l in 3askell. The assoc-in function takes a map, a key se#uence and a new value. $t returns a new map where the nested map key at the end of the se#uence has the new value. For e!ample, a new map where the employer city is changed to *Clayton* can be created as follows&
(assoc-in person ,7emplo'er 7a ress 7cit'- "*la'ton")

The up ate-in function takes a map, a key se#uence, a function and any number of additional arguments. The function is passed the old value of the key at the end of the se#uence and the additional arguments. The value it returns is used as the new value of that key. For e!ample, a new map where the employer /ip code is changed to a string in the ).1. *O$ L 6* format can be created using as follows&
(up ate-in person ,7emplo'er 7a function ress 7Mip- str "-123K") ; using the str

Struct a!s
Fote& 1truct>aps have been deprecated. Eecords are generally recommended instead. A section on Eecords will be added shortly. 1truct>aps are similar to regular maps, but are optimi/ed to take advantage of common keys in multiple instances so they don%t have to be repeated. Their use is similar to that of 2ava Beans. roper e5uals and hash*o e methods are generated for them. Accessor functions that are faster than ordinary map key lookups can easily be created. The create-struct function and efstruct macro, which uses create-struct, both define 1truct>aps. The keys are normally specified with keywords. For e!ample&
( ef vehicle-struct (create-struct 7ma8e 7mo el 7'ear 7color)) ; long wa' ( efstruct vehicle-struct 7ma8e 7mo el 7'ear 7color) ; short wa'

The struct function creates an instance of a given 1truct>ap. Aalues must be specified in the same order as their corresponding keys were specified when the 1truct>ap was defined. Aalues for keys at the end can be omitted and their values will be nil. For e!ample&
( ef vehicle (struct vehicle-struct "Bo'ota" "2rius" 2EEN))

:8

The accessor function creates a function for accessing the value of a given key in instances that avoids performing a hash map lookup. For e!ample&
; !ote the use of ef instea of efn $ecause accessor returns ; a function that is then $oun to "ma8e"( ( ef ma8e (accessor vehicle-struct 7ma8e)) (ma8e vehicle) ; -> "Bo'ota" (vehicle 7ma8e) ; same $ut slower (7ma8e vehicle) ; same $ut slower

Few keys not specified when the 1truct>ap was defined can be added to instances. 3owever, keys specified when the 1truct>ap was defined cannot be removed from instances.

"e#ining Functions
The efn macro defines a function. $ts arguments are the function name, an optional documentation string ,displayed by the oc macro-, the parameter list ,specified with a vector that can be empty- and the function body. The result of the last e!pression in the body is returned. ?very function returns a value, but it may be nil. For e!ample&
( efn parting "returns a %tring parting" ,name(str "Soo $'e, " name)) ; concatenation (println (parting "Rar8")) ; -> Soo $'e, Rar8

Function definitions must appear before their first use. 1ometimes this isn%t possible due to a set of functions that invoke each other. The eclare special form takes any number of function names and creates forward declarations that resolve these cases. For e!ample&
( eclare function-names)

Functions defined with the efn- macro are private. This means they are only visible in the namespace in which they are defined. 0ther macros that produce private definitions, such as efmacro-, are in clo+ure(core(incu$ator. Functions can take a variable number of parameters. 0ptional parameters must appear at the end. They are gathered into a list by adding an ampersand and a name for the list at the end of the parameter list.
( efn power ,$ase : eFponents; Wsing +ava(lang(Rath static metho pow( (re uce /(Rath"pow <1 <2) $ase eFponents)) (power 2 3 K) ; 2 to the 3r C Q; Q to the Kth C KENJ

Function definitions can contain more than one parameter list and corresponding body. ?ach parameter list must contain a different number of parameters. This supports overloading functions based on arity. 0ften it is useful for a body to call the same function with a different number of arguments in order to provide default values for some of them. For e!ample&
( efn parting

:N

"returns a %tring parting in a given language" (,- (parting "Iorl ")) (,name- (parting name "en")) (,name language; con p is similar to a case statement in other languages( ; Ut is escri$e in more etail later( ; Ut is use here to ta8e ifferent actions $ase on whether the ; parameter "language" is set to "en", "es" or something else( (con p C language "en" (str "Soo $'e, " name) "es" (str "D ios, " name) (throw (UllegalDrgument1Fception( (str "unsupporte language " language)))))) (println (parting)) ; -> Soo $'e, Iorl (println (parting "Rar8")) ; -> Soo $'e, Rar8 (println (parting "Rar8" "es")) ; -> D ios, Rar8 (println (parting "Rar8", "F'")) ; -> +ava(lang(UllegalDrgument1Fception7 unsupporte

language F'

Anonymous functions have no name. These are often passed as arguments to a named function. They are handy for short function definitions that are only used in one place. There are two ways to define them, shown below&
( ef 'ears ,1NKE 1NKK 1NJ1 1NQP 1NQO-) (filter (fn ,'ear- (even@ 'ear)) 'ears) ; long wa' w" name arguments -> (1NKE 1NKK) (filter /(even@ <) 'ears) ; short wa' where < refers to the argument

=hen an anonymous function is defined using the fn special form, the body can contain any number of e!pressions. $t can also have a name ,following *fn*- which makes it no longer anonymous and enables it to call itself recursively. =hen an anonymous function is defined in the short way using /((((), it can only contain a single e!pression. To use more than one e!pression, wrap them in the o special form. $f there is only one parameter, it can be referred to with <. $f there are multiple parameters, they are referred to with <1, <2 and so on. For e!ample&
( efn pair-test ,test-fn n1 n2(if (test-fn n1 n2) "pass" "fail")) ; Wse a test-fn that etermines whether ; the sum of its two arguments is an even num$er( (println (pair-test /(even@ (+ <1 <2)) 3 P)) ; -> pass

2ava methods can be overloaded based on parameter types. Clojure functions can only be overloaded on arity. Clojure multimethods however, can be overloaded based on anything. The efmulti and efmetho macros are used together to define a multimethod. The arguments to efmulti are the method name and the dispatch function which returns a value that will be used to select a method. The arguments to efmetho are the method name, the dispatch value that triggers use of the method, the parameter list and the body. The special dispatch value 7 efault is used to designate a method to be used when none of the others match. ?ach efmetho for the same multimethod name must take the same number of arguments. The arguments passed to a multimethod are passed to the dispatch function. :7

3ere%s an e!ample of a multimethod that overloads based on type.


( efmulti what-am-i class) ; class is the ispatch function ( efmetho what-am-i !um$er ,arg- (println arg "is a !um$er")) ( efmetho what-am-i %tring ,arg- (println arg "is a %tring")) ( efmetho what-am-i 7 efault ,arg- (println arg "is something else")) (what-am-i 1N) ; -> 1N is a !um$er (what-am-i "Hello") ; -> Hello is a %tring (what-am-i true) ; -> true is something else

1ince the dispatch function can be any function, including one you write, the possibilities are endless. For e!ample, a custom dispatch function could e!amine its arguments and return a keyword to indicate a si/e such as 7small, 7me ium or 7large. 0ne method for each si/e keyword can provide logic that is specific to a given si/e. )nderscores can be used as placeholders for function parameters that won%t be used and therefore don%t need a name. This is often useful in callback functions which are passed to another function so they can be invoked later. A particular callback function may not use all the arguments that are passed to it. For e!ample&
( efn call$ac81 ,n1 n2 n3- (+ n1 n2 n3)) ; uses all three arguments ( efn call$ac82 ,n1 ; n3- (+ n1 n3)) ; onl' uses 1st : 3r arguments ( efn caller ,call$ac8 value(call$ac8 (+ value 1) (+ value 2) (+ value 3))) (caller call$ac81 1E) ; 11 + 12 + 13 -> 3J (caller call$ac82 1E) ; 11 + 13 -> 2K

The complement function returns a new function that is just like a given function, but returns the opposite logical truth value. For e!ample&
( efn teenager@ ,age- (an (>C age 13) (X age 2E))) ( ef non-teen@ (complement teenager@)) (println (non-teen@ KO)) ; -> true

The comp function composes a new function by combining any number of e!isting ones. They are called from right to left. For e!ample&
( efn times2 ,n- (A n 2)) ( efn minus3 ,n- (- n 3)) ; !ote the use of ef instea of efn $ecause comp returns ; a function that is then $oun to "m'-composition"( ( ef m'-composition (comp minus3 times2)) (m'-composition K) ; KA2 - 3 -> P

The partial function creates a new function from an e!isting one so that it provides fi!ed values for initial parameters and calls the original function. This is called a *partial application*. For e!ample, A is a function that takes any number of arguments and multiplies them together. 1uppose we want a new version of that function that always multiplies by two.
; !ote the use of ef instea of efn $ecause partial returns ; a function that is then $oun to "times2"( ( ef times2 (partial A 2)) (times2 3 K) ; 2 A 3 A K -> 2K

5G

3ere%s an interesting use of both the map and partial functions. =e%ll define functions that use the map function to compute the value of an arbitrary polynomial and its derivative for given ! values. The polynomials are described by a vector of their coefficients. Fe!t, we%ll define functions that use partial to define functions for a specific polynomial and its derivative. Finally, we%ll demonstrate using the functions. The range function returns a la/y se#uence of integers from an inclusive lower bound to an e!clusive upper bound. The lower bound defaults to G, the step si/e defaults to :, and the upper bound defaults to infinity.
( efn- pol'nomial "computes the value of a pol'nomial with the given coefficients for a given value F" ,coefs F; Yor eFample, if coefs contains 3 values then eFponents is (2 1 E)( (let ,eFponents (reverse (range (count coefs))); Rultipl' each coefficient $' F raise to the correspon ing eFponent ; an sum those results( ; coefs go into <1 an eFponents go into <2( (appl' + (map /(A <1 (Rath"pow F <2)) coefs eFponents)))) ( efn- erivative "computes the value of the erivative of a pol'nomial with the given coefficients for a given value F" ,coefs F; Bhe coefficients of the erivative function are o$taine $' ; multipl'ing all $ut the last coefficient $' its correspon ing eFponent( ; Bhe eFtra eFponent will $e ignore ( (let ,eFponents (reverse (range (count coefs))) erivative-coefs (map /(A <1 <2) ($utlast coefs) eFponents)(pol'nomial erivative-coefs F))) ( ef f (partial pol'nomial ,2 1 3-)) ; 2F92 + F + 3 ( ef f-prime (partial erivative ,2 1 3-)) ; KF + 1 (println "f(2) C" (f 2)) ; -> 13(E (println "f4(2) C" (f-prime 2)) ; -> N(E

3ere%s an another way that the polynomial function could be implemented ,suggested by Francesco 1trino-. For a polynomial with coefficients a, b and c, it computes the value for ! as follows& P: Q a, P5 Q b, result is a! L b P: Q a! L b, P5 Q c, result is ,a! L b-! L c Q a!R5 L b! L c
( efn- pol'nomial "computes the value of a pol'nomial with the given coefficients for a given value F" ,coefs F(re uce /(+ (A F <1) <2) coefs))

The memoiMe function takes another function and returns a new function that stores a mapping from previous arguments to previous results for the given function. The new function uses the mapping to avoid invoking the given function with arguments that have already been evaluated. This results in better performance, but also re#uires memory to store the mappings.

5:

The time macro evaluates an e!pression, prints the elapsed time, and returns the e!pression result. $t is used in the following code to measure the time to compute the value of a polynomial at a given ! value. The following e!ample demonstrates memoi/ing a polynomial function&
; !ote the use of ef instea of efn $ecause memoiMe returns ; a function that is then $oun to "memo-f"( ( ef memo-f (memoiMe f)) (println "priming call") (time (f 2)) (println "without memoiMation") ; !ote the use of an un erscore for the $in ing that isn4t use ( ( otimes ,; 3- (time (f 2))) (println "with memoiMation") ( otimes ,; 3- (time (memo-f 2)))

The output produced by this code from a sample run is shown below.
priming call "1lapse time7 K(12Q msecs" without memoiMation "1lapse time7 E(1O2 msecs" "1lapse time7 E(3JP msecs" "1lapse time7 E(1N msecs" with memoiMation "1lapse time7 E(2K1 msecs" "1lapse time7 E(E33 msecs" "1lapse time7 E(E1N msecs"

There are several observations than can be made from this output. The first call to the function f, the *priming call*, takes considerably longer than the other calls. This is true regardless of whether memoi/ation is used. The first call to the memoi/ed function takes longer than the first non-priming call to the original function, due to the overhead of caching its result. 1ubse#uent calls to the memoi/ed function are much faster.

$ava Intero!era%ility
Clojure programs can use all 2ava classes and interfaces. As in 2ava, classes in the +ava(lang package can be used without importing them. 2ava classes in other packages can be used by either specifying their package when referencing them or using the import function. For e!ample&
(import 4(+ava(util *alen ar Sregorian*alen ar) 4(+avaF(swing #Yrame #3a$el))

Also see the 7import directive of the ns macro which is described later. There are two ways to access constants in a 2ava class, shown in the e!amples below&

55

(( +ava(util(*alen ar D20U3) ; -> 3 (( *alen ar D20U3) ; wor8s if the *alen ar class was importe +ava(util(*alen ar"D20U3 *alen ar"D20U3 ; wor8s if the *alen ar class was importe

$nvoking 2ava methods from Clojure code is very easy. Because of this, Clojure doesn%t provide functions for many common operations and instead relies on 2ava methods. For e!ample, Clojure doesn%t provide a function to find the absolute value of a floating point number because the a$s method of the 2ava class +ava(lang(Rath class already does that. 0n the other hand, while that class provides the method maF to find the largest of two values, it only works with two values, so Clojure provides the maF function which takes one or more values. There are two ways to invoke a static method in a 2ava class, shown in the e!amples below&
(( Rath pow 2 K) ; -> 1J(E (Rath"pow 2 K)

There are two ways to invoke a constructor to create a 2ava object, shown in the e!amples below. Fote the use of the ef special form to retain a reference to the new object in a global binding. This is not re#uired. A reference could be retained in several other ways such as adding it to a collection or passing it to a function.
(import 4(+ava(util *alen ar Sregorian*alen ar)) ( ef calen ar (new Sregorian*alen ar 2EEQ *alen ar"D20U3 1J)) ; Dpril 1J, 2EEQ ( ef calen ar (Sregorian*alen ar( 2EEQ *alen ar"D20U3 1J))

There are two ways to invoke an instance method on a 2ava object, shown in the e!amples below&
(( calen ar (( calen ar ((a calen ((get calen a *alen ar"RG!BH 2) get *alen ar"RG!BH) ; -> P ar *alen ar"RG!BH 2) ar *alen ar"RG!BH) ; -> O

The option in the e!amples above where the method name appears first is generally preferred. The option where the object appears first is easier to use inside macro definitions because synta! #uoting can be used instead of string concatenation. This statement will make more sense after reading the *>acros* section ahead. >ethod calls can be chained using the (( macro. The result from the previous method call in the chain becomes the target of the ne!t method call. For e!ample&
(( (( calen ar getBimeZone) getVispla'!ame) ; long wa' ((( calen ar getBimeZone getVispla'!ame) ; -> "*entral %tan ar Bime"

There is also a (@( macro in the clo+ure(core(incu$ator namespace that stops and returns nil if any method in the chain returns null. This avoids getting a !ull2ointer1Fception. The oto macro is used to invoke many methods on the same object. $t returns the value of its first argument which is the target object. This makes it convenient to create the target

54

object with an e!pression that is the first argument ,see the creation of a #Yrame H)$ object in the *Famespaces* section ahead-. For e!ample&
( oto calen ar ((set *alen ar"[1D0 1NQ1) ((set *alen ar"RG!BH *alen ar"DWSW%B) ((set *alen ar"VDB1 1)) ( ef formatter (+ava(teFt(VateYormat"getVateUnstance)) ((format formatter ((getBime calen ar)) ; -> "Dug 1, 1NQ1"

The memfn macro e!pands to code that allows a 2ava method to be treated as a first class function. $t is an alternative to using an anonymous function for calling a 2ava method. =hen using memfn to invoke 2ava methods that take arguments, a name for each argument must be specified. This indicates the arity of the method to be invoked. These names are arbitrary, but they must be uni#ue because they are used in the generated code. The following e!amples apply an instance method ,su$string- to a 2ava object from the first collection ,a %tring-, passing the corresponding item from the second collection ,an int- as an argument&
(println (map /((su$string <1 <2) ,"Roe" "3arr'" "*url'"- ,1 2 3-)) ; -> (oe rr' l') (println (map (memfn su$string $eginUn eF) ,"Roe" "3arr'" "*url'"- ,1 2 3-)) ; -> same

Proxies
The proF' macro e!pands to code that creates a 2ava object that e!tends a given 2ava class and+or implements /ero or more 2ava interfaces. This is often needed to implement callback methods in listener objects that must implement a certain interface in order to register for notifications from another object. For an e!ample, see the *<esktop Applications* section near the end of this article. $t creates an object that e!tends the 2Frame H)$ class and implements the Action;istener interface.

Threads
All Clojure functions implement both the +ava(lang(0unna$le interface and the +ava(util(concurrent(*alla$le interface. This makes it easy to e!ecute them in new 2ava threads. For e!ample&
( efn ela'e -print ,ms teFt(Bhrea "sleep ms) (println teFt)) ; 2ass an anon'mous function that invo8es ela'e -print ; to the Bhrea constructor so the ela'e -print function ; eFecutes insi e the Bhrea instea of ; while the Bhrea o$+ect is $eing create ( ((start (Bhrea ( /( ela'e -print 1EEE ", Iorl H"))) ; prints 2n (print "Hello") ; prints 1st ; output is "Hello, Iorl H"

56

Exception Handling
All e!ceptions thrown by Clojure code are runtime e!ceptions. 2ava methods invoked from Clojure code can still throw checked e!ceptions. The tr', catch, finall' and throw special forms provide functionality similar to their 2ava counterparts. For e!ample&
( efn collection@ ,o$+(println "o$+ is a" (class o$+)) ; *lo+ure collections implement clo+ure(lang(U2ersistent*ollection( (or (coll@ o$+) ; *lo+ure collection@ (instance@ +ava(util(*ollection o$+))) ; #ava collection@ ( efn average ,coll(when-not (collection@ coll) (throw (UllegalDrgument1Fception( "eFpecte a collection"))) (when (empt'@ coll) (throw (UllegalDrgument1Fception( "collection is empt'"))) ; Dppl' the + function to all the items in coll, ; then ivi e $' the num$er of items in it( (let ,sum (appl' + coll)(" sum (count coll)))) (tr' (println "list average C" (average 4(2 3))) ; result is a clo+ure(lang(0atio o$+ect (println "vector average C" (average ,2 3-)) ; same (println "set average C" (average /&2 3))) ; same (let ,al (+ava(util(Drra'3ist()( oto al ((a 2) ((a 3)) (println "Drra'3ist average C" (average al))) ; same (println "string average C" (average "1 2 3 K")) ; illegal argument (catch UllegalDrgument1Fception e (println e) ;((print%tac8Brace e) ; if a stac8 trace is esire ) (finall' (println "in finall'")))

The output produced by the code above follows&


o$+ is a clo+ure(lang(2ersistent3ist list average C P"2 o$+ is a clo+ure(lang(3aMil'2ersistent>ector vector average C P"2 o$+ is a clo+ure(lang(2ersistentHash%et set average C P"2 o$+ is a +ava(util(Drra'3ist Drra'3ist average C P"2 o$+ is a +ava(lang(%tring /XUllegalDrgument1Fception +ava(lang(UllegalDrgument1Fception7 eFpecte a collection> in finall'

Conditional Processing
The if special form tests a condition and e!ecutes one of two e!pressions based on whether the condition evaluates to true. $ts synta! is (if condition then-expr else-expr). The

5D

else e!pression is optional. $f more than one e!pression is needed for the then or else part, use the o special form to wrap them in a single e!pression. For e!ample&
(import 4(+ava(util *alen ar Sregorian*alen ar)) (let ,gc (Sregorian*alen ar() a'-of-wee8 ((get gc *alen ar"VD[;GY;I11\) is-wee8en (or (C a'-of-wee8 *alen ar"%DBW0VD[) (C *alen ar"%W!VD[))(if is-wee8en (println "pla'") ( o (println "wor8") (println "sleep"))))

a'-of-wee8

The when and when-not macros provide alternatives to if when only one branch is needed. Any number of body e!pressions can be supplied without wrapping them in a o. For e!ample&
(when is-wee8en (println "pla'")) (when-not is-wee8en (println "wor8") (println "sleep"))

The if-let macro binds a value to a single binding and chooses an e!pression to evaluate based on whether the value is logically true or false ,e!plained in the * redicates* section-. The following code prints the name of the first person waiting in line or prints *no waiting* if the line is empty.
( efn process-neFt ,waiting-line(if-let ,name (first waiting-line)(println name "is neFt") (println "no waiting"))) (process-neFt 4("#erem'" "Dman a" "Bami")) ; -> #erem' is neFt (process-neFt 4()) ; -> no waiting

The when-let macro is similar to the if-let macro, but it differs in the same way that if differs from when. $t doesn%t support an else part and the then part can contain any number of e!pressions. For e!ample&
( efn summariMe "prints the first item in a collection followe $' a perio for each remaining item" ,coll; 1Fecute the when-let $o ' onl' if the collection isn4t empt'( (when-let ,hea (first coll)(print hea ) ; Telow, ec su$tracts one ( ecrements) from ; the num$er of items in the collection( ( otimes ,; ( ec (count coll))- (print 6()) (println))) (summariMe ,"Roe" "3arr'" "*url'"-) ; -> Roe(( (summariMe ,-) ; -> no output

The con p macro is similar to a case statement in other languages. $t takes a two parameter predicate ,often C or instance@- and an e!pression to act as its second argument. After those it takes any number of value+result e!pression pairs that are evaluated in order. $f the

59

predicate evaluates to true when one of the values is used as its first argument then the corresponding result is returned. An optional final argument specifies the result to be returned if no given value causes the predicate to evaluate to true. $f this is omitted and no given value causes the predicate to evaluate to true then an UllegalDrgument1Fception is thrown. The following e!ample prompts the user to enter a number and prints the name of that number only for :, 5 and 4. 0therwise, it prints *une!pected value*. After that, it e!amines the type of the local binding *value*. $f it is a !um$er, it prints the number times two. $f it is a %tring, it prints the length of the string times two.
(print "1nter a num$er7 ") (flush) ; sta's in a $uffer otherwise (let ,rea er (+ava(io(Tuffere 0ea er( AinA) ; st in line ((rea 3ine rea er) value (tr' (Unteger"parseUnt line) (catch !um$erYormat1Fception e line))- ; use string value if not integer (println (con p C value 1 "one" 2 "two" 3 "three" (str "uneFpecte value, 6"" value 6"))) (println (con p instance@ value !um$er (A value 2) %tring (A (count value) 2))))

The con macro takes any number of predicate+result e!pression pairs. $t evaluates the predicates in order until one evaluates to true and then returns the corresponding result. $f none evaluate to true then an UllegalDrgument1Fception is thrown. 0ften the predicate in the last pair is simply true to handle all remaining cases. The following e!ample prompts the user to enter a water temperature. $t then prints whether the water is free/ing, boiling or neither.
(print "1nter water temperature in *elsius7 ") (flush) (let ,rea er (+ava(io(Tuffere 0ea er( AinA) line ((rea 3ine rea er) temperature (tr' (Yloat"parseYloat line) (catch !um$erYormat1Fception e line))- ; use string value if not float (println (con (instance@ %tring temperature) "invali temperature" (XC temperature E) "freeMing" (>C temperature 1EE) "$oiling" true "neither")))

Iteration
There are many ways to *loop* or iterate through items in a se#uence.

58

The otimes macro e!ecutes the e!pressions in its body a given number of times, assigning values from /ero to one less than that number to a specified local binding. $f the binding isn%t needed ,car -num$er in the e!ample below-, an underscore can be used as its placeholder. For e!ample&
( otimes ,car -num$er 3(println " eal car num$er" (inc car -num$er))) ; a s one to car -num$er

Fote that the inc function is used so that the values :, 5 and 4 are output instead of G, : and 5. The code above produces the following output&
eal car eal car eal car num$er 1 num$er 2 num$er 3

The while macro e!ecutes the e!pressions in its body while a test e!pression evaluates to true. The following e!ample e!ecutes the while body while a given thread is still running&
( efn m'-fn ,ms(println "entere m'-fn") (Bhrea "sleep ms) (println "leaving m'-fn")) (let ,threa (Bhrea ( /(m'-fn 1))((start threa ) (println "starte threa ") (while ((isDlive threa ) (print "(") (flush)) (println "threa stoppe "))

The output from the code above will be similar to the following&
starte threa (((((entere m'-fn( (((((((((((((leaving m'-fn( threa stoppe

List Comprehension
The for and ose5 macros perform list comprehension. They support iterating through multiple collections ,rightmost collection fastest- and optional filtering using 7when and 7while e!pressions. The for macro takes a single e!pression body and returns a la/y se#uence of the results. The ose5 macro takes a body containing any number of e!pressions, e!ecutes them for their side effects, and returns nil. The following e!amples both output names of some spreadsheet cells working down rows and then across columns. They skip the *B* column and only use rows that are less than 4. Fote how the orun function, described later in the *1e#uences* section, is used to force evaluation of the la/y se#uence returned by the for macro.
( ef cols "DT*V") ( ef rows (range 1 K)) ; purposel' larger than nee e to emonstrate 7while

5N

(println "for emo") ( orun (for ,col cols 7when (notC col 6T) row rows 7while (X row 3)(println (str col row)))) (println "6n ose5 emo") ( ose5 ,col cols 7when (notC col 6T) row rows 7while (X row 3)(println (str col row)))

The code above produces the following output&


for D1 D2 *1 *2 V1 V2 ose5 D1 D2 *1 *2 V1 V2 emo

emo

The loop special form, as its name suggests, supports looping. $t and its companion special form recur are described in the ne!t section.

Recursion
Eecursion occurs when a function invokes itself either directly or indirectly through another function that it calls. Common ways in which recursion is terminated include checking for a collection of items to become empty or checking for a number to reach a specific value such as /ero. The former case is often implemented by successively using the neFt function to process all but the first item. The latter case is often implemented by decrementing a number with the ec function. Eecursive calls can result in running out of memory if the call stack becomes too deep. 1ome programming languages address this by supporting *tail call optimi/ation* ,TC0-. 2ava doesn%t currently support TC0 and neither does Clojure. 0ne way to avoid this issue in Clojure is to use the loop and recur special forms. Another way is to use the trampoline function. The loop+recur idiom turns what looks like a recursive call into a loop that doesn%t consume stack space. The loop special form is like the let special form in that they both establish local bindings, but it also establishes a recursion point that is the target of calls to recur. The bindings specified by loop provide initial values for the local bindings. Calls to recur cause control to return to the loop and assign new values to its local bindings. The number of arguments passed to recur must match the number of bindings in the loop. Also, recur can only appear as the last call in the loop. 57

( efn factorial-1 ,num$er"computes the factorial of a positive integer in a wa' that oesn4t consume stac8 space" (loop ,n num$er factorial 1(if (Mero@ n) factorial (recur ( ec n) (A factorial n))))) (println (time (factorial-1 P))) ; -> "1lapse time7 E(EO1 msecs"6n12E

The efn macro, like the loop special form, establishes a recursion point. The recur special form can also be used as the last call in a function to return to the beginning of that function with new arguments. Another way to implement the factorial function is to use the re uce function. This was described back in the *Collections* section. $t supports a more functional, less imperative style. )nfortunately, in this case, it is less efficient. Fote that the range function takes a lower bound that is inclusive and an upper bound that is e!clusive.
( efn factorial-2 ,num$er- (re uce A (range 2 (inc num$er)))) (println (time (factorial-2 P))) ; -> "1lapse time7 E(33P msecs"6n12E

The same result can be obtained by replacing re uce with appl', but that takes even longer. This illustrates the importance of understanding the characteristics of functions when choosing between them. The recur special form isn%t suitable for mutual recursion where a function calls another function which calls back to the original function. The trampoline function, not covered here, does support mutual recursion.

Predicates
Clojure provides many functions that act as predicates, used to test a condition. They return a value that can be interpreted as true or false. The values false and nil are interpreted as false. The value true and every other value, including /ero, are interpreted as true. redicate functions usually have a name that ends in a #uestion mark. Eeflection involves obtaining information about an object other than its value, such as its type. There are many predicate functions that perform reflection. redicate functions that test the type of a single object include class@, coll@, ecimal@, ela'@, float@, fn@, instance@, integer@, isa@, 8e'wor @, list@, macro@, map@, num$er@, se5@, set@, string@ and vector@. 1ome non-predicate functions that perform reflection include ancestors, $ases, class, ns-pu$lics and parents. redicate functions that test relationships between values include X, XC, C, notC, CC, >, >C, compare, istinct@ and i entical@. redicate functions that test logical relationships include an , or, not, true@, false@ and
nil@

4G

redicate functions that test se#uences, most of which were discussed earlier, include empt'@, not-empt', ever'@, not-ever'@, some and not-an'@. redicate functions that test numbers include even@, neg@, o
@, pos@

and Mero@.

Se&uences
1e#uences are logical views of collections. >any things can be treated as se#uences. These include 2ava collections, Clojure-specific collections, strings, streams, directory structures and (>; trees. >any Clojure functions return a la/y se#uence. This is a se#uence whose items can be the result of function calls that aren%t evaluated until they are needed. A benefit of creating a la/y se#uence is that it isn%t necessary to anticipate how many items in it will actually be used at the time the se#uence is created. ?!amples of functions and macros that return la/y se#uences include& cache-se5, concat, c'cle, istinct, rop, rop-last, rop-while, filter, for, interleave, interpose, iterate, laM'-cat, laM'-se5, line-se5, map, partition, range, re-se5, remove, repeat, replicate, ta8e, ta8e-nth, ta8e-while and tree-se5. ;a/y se#uences are a common source of confusion for new Clojure developers. For e!ample, what does the following code outputJ
(map /(println <) ,1 2 3-)

=hen run in a E? ;, this outputs the values :, 5 and 4 on separate lines interspersed with a se#uence of three nils which are the return values from three calls to the println function. The E? ; always fully evaluates the results of the e!pressions that are entered. 3owever, when run as part of a script, nothing is output by this code. This is because the map function returns a la/y se#uence containing the results of applying its first argument function to each of the items in its second argument collection. The documentation string for the map function clearly states that it returns a la/y se#uence. There are many ways to force the evaluation of items in a la/y se#uence. Functions that e!tract a single item such as first, secon , nth and last do this. The items in the se#uence are evaluated in order, so items before the one re#uested are also evaluated. For e!ample, re#uesting the last item causes every item to be evaluated. $f the head of a la/y se#uence is held in a binding, once an item has been evaluated its value is cached so it isn%t reevaluated if re#uested again. The orun and oall functions force the evaluation of items in a single la/y se#uence. The ose5 macro, discussed earlier in the *$teration* section, forces the evaluation of items in one or more la/y se#uences. The for macro, discussed in that same section, does not force evaluation and instead returns another la/y se#uence. )sing ose5 or orun is appropriate when the goal is to simply cause the side effects of the evaluations to occur. The results of the evaluations are not retained, so less memory is consumed. They both return nil. )sing oall is appropriate when the evaluation results

4:

need to be retained. $t holds the head of the se#uence which causes the results to be cached and it returns the evaluated se#uence. The table below illustrates the options for forcing the evaluation of items in a la/y se#uence. Discard evaluation results Retain evaluation results and onl cause side effects !perate on a single se"uence
oall orun ose5

!perate on an num#er of se"uences F+A $ith list comprehension s nta%

The ose5 macro is typically preferred over the orun function because the code is easier to read. $t is also faster because a call to map inside orun creates another se#uence. For e!ample, the following lines both produce the same output&
( orun (map /(println <) ,1 2 3-)) ( ose5 ,i ,1 2 3-- (println i))

$f a function creates a la/y se#uence that will have side effects when its items are evaluated, in most cases it should force the evaluation of the se#uence with oall and return its result. This makes the timing of the side effects more predictable. 0therwise callers could evaluate the la/y se#uence any number of times resulting in the side effects being repeated. The following e!pressions all output :, 5, 4 on separate lines, but they have different return values. The o special form is used here to implement an anonymous function that does more than one thing, print the value passed in and return it.
( ose5 ,item ,1 2 3-- (println item)) ; -> nil ( orun (map /(println <) ,1 2 3-)) ; -> nil ( oall (map /( o (println <) <) ,1 2 3-)) ; -> (1 2 3)

;a/y se#uences make it possible to create infinite se#uences since all the items don%t need to be evaluated. For e!ample&
( efn f "s5uare the argument an ivi e $' 2" ,F(println "calculating f of" F) (" (A F F) 2(E)) ; ; ; ; ( *reate an infinite se5uence of results from the function f for the values E through infinit'( !ote that the hea of this se5uence is $eing hel in the $in ing "f-se5"( Bhis will cause the values of all evaluate items to $e cache ( ef f-se5 (map f (iterate inc E)))

; Yorce evaluation of the first item in the infinite se5uence, (f E)( (println "first is" (first f-se5)) ; -> E(E ; ; ; ( Yorce evaluation of the first three items in the infinite se5uence( %ince the (f E) has alrea ' $een evaluate , onl' (f 1) an (f 2) will $e evaluate ( oall (ta8e 3 f-se5))

45

(println (nth f-se5 2)) ; uses cache

result -> 2(E

3ere%s a variation on the previous code that does not hold the head of the la/y se#uence in a binding. Fote how the se#uence is defined as the result of a function rather than the value of a binding. The results for evaluated items are not cached. This reduces memory re#uirements, but is less efficient when items are re#uested more than once.
( efn f-se5 ,- (map f (iterate inc E))) (println (first (f-se5))) ; evaluates (f E), $ut oesn4t cache result (println (nth (f-se5) 2)) ; evaluates (f E), (f 1) an (f 2)

Another way to avoid holding the head of a la/y se#uence in a binding is to pass the la/y se#uence directly to a function that will evaluate its items. For e!ample&
( efn consumer ,se5; %ince se5 is a local $in ing, the evaluate items in it ; are cache while in this function an then gar$age collecte ( (println (first se5)) ; evaluates (f E) (println (nth se5 2))) ; evaluates (f 1) an (f 2) (consumer (map f (iterate inc E)))

In!ut'Out!ut
Clojure provides a minimal set of functions that perform $+0 operations. 1ince 2ava classes are easy to use from Clojure code, the classes in the +ava(io package can be used directly. 3owever, the clojure.java.io library makes many uses of those classes easier. The predefined, special symbols AinA, AoutA and AerrA are set to stdin, stdout and stderr by default. To flush buffered output in AoutA, use (flush) which is the same as ((flush AoutA). The bindings for these symbols can be modified. For e!ample, to redirect output that goes to stdout by default so it goes to a file named *m'(log*, surround the code to be affected as follows&
($in ing ,AoutA (+ava(io(YileIriter( "m'(log")((( (println "Bhis goes to the file m'(log(") ((( (flush))

The print function prints the string representation of any number of objects, with a space between each one, to the stream in the special symbol AoutA. The println function is like print, but it outputs a newline character at the end. By default, it also flushes its output. This can be changed by binding the special symbol Aflush-onnewlineA to false. The newline function writes a newline character to the stream in AoutA . Calling print followed by newline is e#uivalent to println. The pr and prn functions are like their print and println counterparts, but their output is in a form that can be read by the Clojure reader. They are suitable for seriali/ing Clojure data 44

structures. By default, they do not print metadata. This can be changed by binding the special symbol Aprint-metaA to true. The following e!amples demonstrate all four of the printing functions. Fote how the output for strings and characters differs depending on whether the print or pr functions are used.
(let ,o$+1 "foo" o$+2 &7letter 6a 7num$er (Rath"2U))- ; a map (println "Gutput from print7") (print o$+1 o$+2) (println "Gutput from println7") (println o$+1 o$+2) (println "Gutput from pr7") (pr o$+1 o$+2) (println "Gutput from prn7") (prn o$+1 o$+2))

The code above produces the following output&


Gutput from print7 foo &7letter a, 7num$er 3(1K1PN2JP3PQNON3)Gutput from println7 foo &7letter a, 7num$er 3(1K1PN2JP3PQNON3) Gutput from pr7 "foo" &7letter 6a, 7num$er 3(1K1PN2JP3PQNON3)Gutput from prn7 "foo" &7letter 6a, 7num$er 3(1K1PN2JP3PQNON3)

All the printing functions discussed above add a space between the output of their arguments. The str function can be used to avoid this. $t concatenates the string representations of its arguments. For e!ample&
(println "foo" 1N) ; -> foo 1N (println (str "foo" 1N)) ; -> foo1N

The print-str, println-str, pr-str and prn-str functions are similar to their print, println, pr and prn counterparts, but they print to a string that is returned instead of printing to AoutA. The printf function is similar to print, but uses a format string. The format function is similar to printf, but prints to a string that is returned instead of printing to AoutA. The with-out-str macro captures the output from all the e!pressions in its body in a string and returns it. The with-open macro takes any number of bindings to objects on which (close should be called after the e!pressions in its body are e!ecuted. $t is ideal for processing resources such as files and database connections. The line-se5 function takes a +ava(io(Tuffere 0ea er and returns a la/y se#uence of all the lines of te!t in it. The significance of returning a *la/y* se#uence is that it doesn%t really

46

read all of the lines when it is called. That could consume too much memory. $nstead it reads a line each time one is re#uested from the la/y se#uence. The following e!ample demonstrates both with-open and line-se5. $t reads all the lines in a file and prints those that contain a given word.
(use 4,clo+ure(+ava(io 7onl' (rea er)-) ( efn print-if-contains ,line wor (when ((contains line wor ) (println line))) (let ,file "stor'(tFt" wor "fur"; with-open will close the rea er after ; evaluating all the eFpressions in its $o '( (with-open ,r r (rea er file)( ose5 ,line (line-se5 r r)- (print-if-contains line wor ))))

The slurp function reads the entire contents of a file into a string and returns it. The spit function writes a string to a given file and closes it. This article only scratches the surface of what the core and java.io libraries provide. $t%s a worthwhile investment to read through the file clo+ure"+ava"io(cl+ to learn about the other functions it defines.

"estructuring
<estructuring can be used in the parameter list of a function or macro to e!tract parts of collections into local bindings. $t can also be used in bindings created using the let special form and the $in ing macro. For e!ample, suppose we want a function that takes a list or vector and returns the sum of its first and third items.
( efn approach1 ,num$ers(let ,n1 (first num$ers) n3 (nth num$ers 2)(+ n1 n3))) ; !ote the un erscore use to represent the ; secon item in the collection which isn4t use ( ( efn approach2 ,,n1 ; n3-- (+ n1 n3)) (approach1 ,K P J O-) ; -> 1E (approach2 ,K P J O-) ; -> 1E

The ampersand character can be used with destructuring to capture the remaining items in a collection. For e!ample&
( efn name-summar' ,,name1 name2 : others-(println (str name1 ", " name2) "an " (count others) "others")) (name-summar' ,"Roe" "3arr'" "*url'" "%hemp"-) ; -> Roe, 3arr' an 2 others

4D

The 7as keyword can be used to retain access to the entire collection that is being destructured. 1uppose we want a function that takes a list or vector and returns the sum of the first and third items divided by the sum of all the items.
( efn first-an -thir -percentage ,,n1 ; n3 7as coll-(" (+ n1 n3) (appl' + coll))) (first-an -thir -percentage ,K P J O-) ; ratio re uce from 1E"22 -> P"11

<estructuring can also be used to e!tract values from maps. 1uppose we want a function that takes a map of sales figures where each key is a month and each value is the sales total for that month. The function sums the sales for summer months and divides by the sales for all the months to determine the percentage of all sales that occurred in the summer.
( efn summer-sales-percentage ; Bhe 8e'wor s $elow in icate the 8e's whose values ; shoul $e eFtracte $' estructuring( ; Bhe non-8e'wor s are the local $in ings ; into which the values are place ( ,&+une 7+une +ul' 7+ul' august 7august 7as all)(let ,summer-sales (+ +une +ul' august) all-sales (appl' + (vals all))(" summer-sales all-sales))) ( ef sales & 7+anuar' 1EE 7fe$ruar' 2EE 7march E 7april 3EE 7ma' 2EE 7+une 1EE 7+ul' KEE 7august PEE 7septem$er 2EE 7octo$er 3EE 7novem$er KEE 7 ecem$er JEE)) (summer-sales-percentage sales) ; ratio re uce from 1EEE"33EE -> 1E"33

$t is common when destructuring maps to use local binding names whose names match corresponding keys. For e!ample, in the code above we used &+une 7+une +ul' 7+ul' august 7august 7as all). This can be simplified using 78e's. For e!ample, &78e's ,+une +ul' august- 7as all).

(ames!aces
2ava groups methods in classes and classes in packages. Clojure groups things that are named by symbols in namespaces. These include Aars, Eefs, Atoms, Agents, functions, macros and namespaces themselves. 1ymbols are used to assign names to functions, macros and bindings. 1ymbols are partitioned into namespaces. There is always a current default namespace, initially set to *user*, and it is stored in the special symbol AnsA. The default namespace can be changed in two ways. The in-ns function merely changes it. The ns macro does that and much more. 0ne e!tra thing it does is make all the symbols in the clo+ure(core namespace available in the new namespace ,using refer which is described later-. 0ther features of the ns macro are described later. The *user* namespace provides access to all the symbols in the clo+ure(core namespace. The same is true of any namespace that is made the default through use of the ns macro.

49

$n order to access items that are not in the default namespace they must be namespace#ualified. This is done by preceding a name with a namespace name and a slash. For e!ample, the clojure.string library defines the +oin function. $t creates a string by concatenating a given separator string between the string representation of all the items in a se#uence. The namespace-#ualified name of this function is clo+ure(string"+oin. The re5uire function loads Clojure libraries. $t takes one or more #uoted namespace names. For e!ample&
(re5uire 4clo+ure(string)

This merely loads the library. Fames in it must still be namespace-#ualified in order to refer to them. Fote that namespace names are separated from a name with a slash, whereas 2ava package names are separated from a class name with a period. For e!ample&
(clo+ure(string"+oin "L" ,1 2 3-) ; -> "1L2L3"

The alias function creates an alias for a namespace to reduce the amount of typing re#uired to namespace-#ualify symbols. Aliases are defined and only known within the current namespace. For e!ample&
(alias 4su 4clo+ure(string) (su"+oin "L" ,1 2 3-) ; -> "1L2L3"

The refer function makes all the symbols in a given namespace accessible in the current namespace without namespace-#ualifying them. An e!ception is thrown if a name in the given namespace is already defined in the current namespace. For e!ample&
(refer 4clo+ure(string)

Fow the previous code can be written as&


(+oin "L" ,1 2 3-) ; -> "1L2L3"

The combination of re5uire and refer is used often, so the shortcut function use is provided to do both.
(use 4clo+ure(string)

The ns macro, mentioned earlier, changes the default namespace. $t is typically used at the top of a source file. $t supports the directives 7re5uire, 7use and 7import ,for importing 2ava classes- that are alternatives to using their function forms. )sing these is preferred over using their function forms. $n the e!ample below, note the use of 7as to create an alias for a namespace. Also note the use of 7onl' to load only part of a Clojure library.
(ns com(ociwe$( emo (7re5uire ,clo+ure(string 7as su-) ; assumes this epen enc'7 ,org(clo+ure"math(numeric-tower "E(E(1"(7use ,clo+ure(math(numeric-tower 7onl' (gc , s5rt)-) (7import (+ava(teFt !um$erYormat) (+avaF(swing #Yrame #3a$el))) (println (su"+oin "L" ,1 2 3-)) ; -> 1L2L3

48

(println (gc 2O O2)) ; -> N (println (s5rt P)) ; -> 2(23JEJONOOKNNON (println ((format (!um$erYormat"getUnstance) Rath"2U)) ; -> 3(1K2 ; %ee the screenshot that follows this co e( ( oto (#Yrame( "Hello") ((a (#3a$el( "Hello, Iorl H")) ((pac8) ((setVefault*loseGperation #Yrame"1]UB;G!;*3G%1) ((set>isi$le true))

The create-ns function creates a new namespace, but doesn%t make it the default. The ef function defines a symbol in the default namespace with an optional initial value. The intern function defines a symbol in a given namespace ,if the symbol doesn%t already e!ist- and optionally gives it an initial value. Fote that the symbol name needs to be #uoted for intern, but not for ef. This is because ef is a special form that doesn%t evaluate all of its arguments, whereas intern is a function, which means it evaluates all of its arguments. For e!ample&
( ef foo 1) (create-ns 4com(ociwe$( emo) (intern 4com(ociwe$( emo 4foo 2) (println (+ foo com(ociwe$( emo"foo)) ; -> 3

The ns-interns function returns a map containing all the symbols defined in a given, currently loaded namespace. The map has keys that are %'m$ol objects for the names and values which are >ar objects representing functions, macros and bindings. For e!ample&
(ns-interns 4clo+ure(math(numeric-tower)

The all-ns function returns a se#uence of the currently loaded namespaces. The following namespaces are loaded by default when a Clojure program is run& clo+ure(core, clo+ure(main, clo+ure(set, clo+ure(Fml, clo+ure(Mip and user. The following additional namespaces are loaded by default in a E? ;& clo+ure(repl and clo+ure(+ava(+ava oc. The namespace function returns the namespace of a given symbol or keyword. 0ther namespace related functions not discussed here include ns-aliases, ns-imports, nsmap, ns-name, ns-pu$lics, ns-refers, ns-unalias, ns-unmap and remove-ns.

Some Fine Print


A %'m$ol object has a %tring name and a %tring namespace name ,called ns-, but no value. The fact that it uses a 1tring namespace name instead of a !amespace object reference allows 4N

it to be in a namespace that doesn%t yet e!ist. A >ar objects has references to a %'m$ol object ,called s'm-, a !amespace object ,called ns- and an G$+ect object which is its *root value* ,called root-. !amespace objects have a reference to a Rap that holds associations between %'m$ol objects and >ar objects ,named mappings-. They also have a reference to a Rap that holds associations between %'m$ol aliases and !amespace objects ,called namespaces-. 1ee the class diagram below which shows a small subset of the attributes and key relationships between the 2ava classes and interfaces in the Clojure implementation. $n Clojure, the term *interning* typically refers to adding a %'m$ol-to->ar mapping to a !amespace.

etadata
Clojure metadata is data attached to a symbol or collection that is not related to its logical value. Two objects that are logically e#ual, such as two cards that are both the king of clubs, can have different metadata. For e!ample, metadata can be used to indicate whether a card is bent. For the purpose of most card games, the fact that a card is bent has no bearing on the value of the card.
( efstruct car -struct 7ran8 7suit) ( ef car 1 (struct car -struct 78ing 7clu$)) ( ef car 2 (struct car -struct 78ing 7clu$)) (println (CC car 1 car 2)) ; same i entit'@ -> false (println (C car 1 car 2)) ; same value@ -> true ( ef car ( ef car (println (println (println 2 9&7$ent true) car 2) ; a s meta ata at rea -time 2 (with-meta car 2 &7$ent true))) ; a s meta ata at run-time (meta car 1)) ; -> nil (meta car 2)) ; -> &7$ent true) (C car 1 car 2)) ; still same value espite meta ata iff( -> true

47

1ome metadata names have a designated use in Clojure. 7private has a boolean value that indicates whether access to a Aar is restricted to the namespace in which it is defined. 7 oc is a documentation string for a Aar. 7test has a boolean value that indicates whether a function that takes no arguments is a test function. is a string class name or a *lass object that describes the 2ava type of a Aar or the return type of a function. These are referred to as *type hints*. roviding them can improve performance. To see where in your code Clojure is using reflection to determine types, and therefore taking a performance hit, set the global variable Awarn-on-reflectionA to true.
7tag

1ome metadata is automatically attached to Aars by the Clojure compiler. 7file is the string name of the file that defines the Aar. 7line is the integer line number within the file where the Aar is defined. 7name is a %'m$ol that provides a name for the Aar. 7ns is a !amespace object that describes the namespace in which the Aar is defined. 7macro is a boolean that indicates whether a Aar is a macro as opposed to a function or binding. 7arglist is a list of vectors where each vector describes the names of the parameters a function accepts. Eecall that a function can have more than one parameter list and body. Functions and macros, both represented by a >ar object, have associated metadata. For e!ample, enter the following in a E? ;& (meta (var reverse)). The output will be similar to the following, but on a single line&
& 7ns /X!amespace clo+ure(core>, 7name reverse, 7file "core(cl+", 7line J3E, 7arglists (,coll-), 7 oc "0eturns a se5 of the items in coll in reverse or er( !ot laM'("

The source macro, in the clojure.repl library, uses this metadata to retrieve the source code for a given function or macro. For e!ample&
(source reverse)

The code above produces the following output&


( efn reverse "0eturns a se5 of the items in coll in reverse or er( !ot laM'(" ,coll(re uce con+ nil coll))

acros
>acros are used to add new constructs to the language. They are code that generates code at read-time. =hile functions always evaluate all their arguments, macros can decide which of their arguments will be evaluated. This is important for implementing forms like (if condition then-expr else-expr). $f the condition is true, only the *then* e!pression should be evaluated. $f the condition is false, only the *else* e!pression should be evaluated. This 6G

means that if cannot be implemented as a function ,it is in fact a special form, not a macro-. 0ther forms that must be implemented as macros for this reason include an and or because they need to *short-circuit*. To determine whether a given operation is implemented as a function or a macro, either enter ( oc name) in a E? ; or e!amine its metadata. $f it is a macro then the metadata will contain a 7macro key with a value of true. For e!ample, to determine this for an , enter the following code in a E? ;&
((meta (var an )) 7macro) ; long wa' -> true ((meta /4an ) 7macro) ; slightl' shorter wa' -> true

;et%s walk through some e!amples of writing and using macros. 1uppose there are many places in our code that need to take different actions based on whether a number is really close to /ero, negative or positive. =e want to avoid code duplication. This must be implemented as a macro instead of a function because only one of the three actions should be evaluated. The efmacro macro defines a macro.
( efmacro aroun -Mero ,num$er negative-eFpr Mero-eFpr positive-eFpr?(let ,num$er/ .num$er- ; so num$er is onl' evaluate once (con (X (Rath"a$s num$er/) 1e-1P) .Mero-eFpr (pos@ num$er/) .positive-eFpr true .negative-eFpr)))

The Eeader e!pands calls to the aroun -Mero macro into a call to the let special form. That contains a call to the con function whose arguments are its conditions and return values. The let special form is used here for efficiency in the event that the first parameter, num$er, is passed as an e!pression instead of a simple value. $t evaluates num$er once and then uses its value in two places within the con . The auto-gensym num$er/ is used to generate a uni#ue symbol name so there is no chance the binding name can conflict with that of another symbol. This enables the creation of hygienic macros. The back-#uote ,a.k.a. synta! #uote- at the beginning of the macro definition prevents everything inside from being evaluated unless it is un#uoted. This means the contents will appear literally in the e!pansion, e!cept items preceded by a tilde ,in this case, num$er, Mero-eFpr, positive-eFpr and negative-eFpr-. =hen a symbol name is preceded by a tilde inside a synta! #uoted list, its value is substituted. Bindings in synta! #uoted lists whose values are se#uences can be preceded by .= to substitute their individual items. 3ere are two e!ample uses of this macro where the e!pected output is *+*.
(aroun -Mero E(1 (println "-") (println "E") (println "+")) (println (aroun -Mero E(1 "-" "E" "+")) ; same thing

To e!ecute more than one form for one of the cases, wrap them in a o form. For e!ample, if the number represented a temperature and we had a log function to write to a log file, we might write this&
(aroun -Mero E(1 ( o (log "reall' col H") (println "-")) (println "E")

6:

(println "+"))

To verify that this macro is e!panded properly, enter the following in a E? ;&
(macroeFpan -1 4(aroun -Mero E(1 (println "-") (println "E") (println "+")))

This will output the following on a single line without the indentation&
(clo+ure(core"let ,num$er;;33Q2;;auto;; E(1(clo+ure(core"con (clo+ure(core"X (Rath"a$s num$er;;33Q2;;auto;;) 1(E1-1P) (println "E") (clo+ure(core"pos@ num$er;;33Q2;;auto;;) (println "+") true (println "-")))

3ere%s a function that uses the macro to return a word describing a number.
( efn num$er-categor' ,num$er(aroun -Mero num$er "negative" "Mero" "positive"))

3ere are some e!ample uses.


(println (num$er-categor' -E(1)) ; -> negative (println (num$er-categor' E)) ; -> Mero (println (num$er-categor' E(1)) ; -> positive

1ince macros don%t evaluate their arguments, un#uoted function names can be passed to them and calls to the functions with arguments can be constructed. Function definitions cannot do this and instead must be passed anonymous functions that wrap calls to functions. 3ere%s a macro that takes two arguments. The first is a function that e!pects one argument that is a number of radians, such as a trigonometry function. The second is a number of degrees. $f this were written as a function instead of a macro, we would have to pass /(Rath"sin <) instead of simply Rath"sin for the function. Fote the use of the / suffi! to generate uni#ue, local binding names. This is sometimes necessary to avoid collisions with other bindings. Both / and . must be used inside a synta! #uoted list.
( efmacro trig-'-categor' ,fn egrees?(let ,ra ians/ (Rath"to0a ians . egrees) result/ (.fn ra ians/)(num$er-categor' result/)))

;et%s try it. The e!pected output from the code below is */ero*, *positive*, */ero* and *negative*.
( ose5 ,angle (range E 3JE NE)- ; E, NE, 1QE an (println (trig-'-categor' Rath"sin angle))) 2OE

>acro names cannot be passed as arguments to functions. For e!ample, a macro name such as an cannot be passed to the re uce function. A workaround is to define an anonymous function that calls the macro. For e!ample, (fn ,F '- (an F ')) or /(an <1 <2). The macro is e!panded inside the anonymous function body at read-time. =hen this function is

65

passed to another function such as re uce, a function object rather than a macro name is passed. >acro calls are processed at read-time.

Concurrency
=ikipedia has a great definition of concurrency& *Concurrency is a property of systems in which several computations are e!ecuting and overlapping in time, and potentially interacting with each other. The overlapping computations may be e!ecuting on multiple cores in the same chip, preemptively time-shared threads on the same processor, or e!ecuted on physically separated processors.* The primary challenge of concurrency is managing access to shared, mutable state. >anaging concurrency with locks is hard. $t re#uires determining which objects need to be locked and when they need to be locked. These decisions need to be reevaluated when the code is modified or new code is added. $f a developer forgets to lock objects that need to be locked or locks them at the wrong times, bad things can happen. These include deadlocks and race conditions. $f objects are locked unnecessarily, there is a performance penalty. 1upport for concurrency is one of the main reasons why many developers choose to use Clojure. All data is immutable unless e!plicitly marked as mutable by using the reference types Aar, Eef, Atom and Agent. These provide safe ways to manage shared state and are described in the ne!t section titled *Eeference Types*. $t is easy to run any Clojure function, including user-written functions that are either named or anonymous, in a new thread. 1ee the earlier discussion on threads in the *2ava $nteroperability* section. 1ince Clojure can use all 2ava classes and interfaces, it can use all the 2ava concurrency capabilities. A great source of information on these is the book *2ava Concurrency $n ractice*. This book contains e!cellent advice for managing concurrency using 2ava, but following the advice is not easy. $n most cases, using Clojure reference types is easier than using 2ava-based concurrency. $n addition to reference types, Clojure provides many functions that assist with running code in different threads. The future macro runs a body of e!pressions in a different thread using one of the thread pools ,*ache Bhrea 2ool- that are also used by Agents ,described later-. This is useful for long running e!pressions whose results aren%t needed immediately. The result is obtained by dereferencing the object returned by future. $f the body hasn%t yet completed when its result is re#uested, the current thread blocks until it does. 1ince a thread from an Agent thread pool is used, shut own-agents should be called at some point so those threads are stopped and the application can e!it. To demonstrate using future, a println was added to the erivative function described at the end of the *<efining Functions* section. $t helps identify when that function is e!ecuted. Fote the order of the output from the code below&

64

(println "creating future") ( ef m'-future (future (f-prime 2))) ; f-prime is calle (println "create future") (println "result is" =m'-future) (shut own-agents)

in another threa

$f the f-prime function doesn%t complete #uickly, the output from the code above will be&
creating future create future erivative entere result is N(E

The pmap function applies a function to all the items in a collection in parallel. $t provides better performance than the map function when the function being applied is time consuming compared to the overhead of managing the threads. The clo+ure(parallel namespace provides many more functions that help with paralleli/ing code. These include par, p istinct, pfilter- upes, pfilter-nils, pmaF, pmin, pre uce, psort, psummar' and pvec.

Re#erence )y!es
Eeference types are mutable references to immutable data. There are four references types in Clojure& Aars, Eefs, Atoms and Agents. They have many things in common&

They can hold any kind of object. They can be dereferenced to retrieve the object they hold with the eref function or the = reader macro. They support validators which are functions that are invoked when the value changes. $f the new value is valid, they return true. 0therwise they either return false or throw an e!ception. $f they simply return false, an Ullegal%tate1Fception with the message *$nvalid reference state* will be thrown. They support watchers which are Agents. =hen the value of a watched reference changes, the Agent is notified. For more detail, see the *Agents* section.

The table below summari/es some of the differences between the four reference types and the functions used to create and modify them. ?ach of the functions in the table below are described later.
Var Purpose synchronous changes to a single, thread-local value Ref synchronous, coordinated changes to one or more values &tom synchronous changes to a single value &gent asynchronous changes to a single value

'o create 'o modif

( ef name initial-value) ( ef name newvalue)


sets new root value

(ref initialvalue)

(atom initialvalue)

(agent initialvalue)

(alter-var-root (var name) update-fn args)


atomically sets new root value

(ref-set ref new- (resetH atom new- (sen agent value) value) update-fn must be inside a os'nc (compare-an -setH arguments) (alter ref atom current(sen -off agent update-fn value new-value) update-fn arguments) arguments) (swapH atom

66

(setH name newvalue)


sets new, thread-local value inside a $in ing form

os'nc (commute ref update-fn arguments) must be inside a os'nc


must be inside a

update-fn arguments)

Vars
Aars are references that can have a root binding that is shared by all threads and can have a different value in each thread ,thread-local-. To create a Aar and give it a root binding&
( ef name value)

roviding a value is optional. $f none is given then the Aar is said to be *unbound*. The same form is used to change the root binding of an e!isting Aar. There are two ways to create a thread-local binding for an e!isting Aar&
($in ing ,name expression- body) (setH name expression) ; insi e a $in ing that $oun the same name

)se of the binding macro was described earlier. The following e!ample demonstrates using it in conjunction with the setH special form. That changes the thread-local value of a Aar that was bound to a thread-local value by the $in ing macro.
( ef 97 'namic v 1) ; nee $in ing " 'namic" meta ata so v can $e change in a

( efn change-it ,(println "2) v C" v) ; -> 1 ( ef v 2) ; changes root value (println "3) v C" v) ; -> 2 ($in ing ,v 3- ; $in s a threa -local value (println "K) v C" v) ; -> 3 (setH v K) ; changes threa -local value (println "P) v C" v)) ; -> K (println "J) v C" v)) ; threa -local value is gone now -> 2 (println "1) v C" v) ; -> 1 (let ,threa (Bhrea ( /(change-it))((start threa ) ((+oin threa )) ; wait for threa to finish (println "O) v C" v) ; -> 2

The use of Aars is often frowned upon because changes to their values are not coordinated across threads. For e!ample, a thread A could use the root value of a Aar and then later discover that another thread B changed that value before thread A finished e!ecuting. 6D

Refs
Eefs are used to ensure that changes to one or more bindings are coordinated between multiple threads. This coordination is implemented using 1oftware Transactional >emory ,1T>-. Eefs can only be modified inside a transaction. 1T> has properties that are similar to database transactions. All changes made inside an 1T> transaction only become visible to other threads at a single point in time when the transaction commits. This makes them both atomic and isolated. Aalidation functions make it possible to insure that changes are consistent with the values of other data. Code to be e!ecuted inside a transaction appears inside the body of a call to the os'nc macro which demarcates the transaction. =hile inside a transaction, Eefs that are changed have a private, in-transaction value that is not seen by other threads until the transaction commits. $f no e!ceptions are thrown before the end of the transaction is reached then changes to Eefs made in the transaction are committed. This means the in-transaction changes become visible outside the transaction. $f an e!ception is thrown from any code e!ecuted inside the transaction, including those thrown from validation functions, the transaction rolls back. This means the in-transaction changes are discarded. =hile in a transaction, if an attempt is made to read or modify a Eef that has been modified in another transaction that has committed since the current transaction started ,a conflict-, the current transaction will retry. This means it will discard all its in-transaction changes and return to the beginning of the os'nc body. There are no guarantees about when a transaction will detect a conflict or when it will begin a retry, only that they will be detected and retries will be performed. $t is important that the code e!ecuted inside transactions be free of side effects since it may be run multiple times due to these retries. 0ne way to support calls to functions that have side effects is to make the calls in actions that are sent to agents from inside a transaction. Those are held until the transaction completes. $f the transaction commits then the actions are sent once regardless of the number of retries that occur. $f the transaction rolls back then the actions are not sent. The ref function creates a new Eef object. 0ne way to create a Eef and retain access to it is to use the ef special form.
( ef name (ref value))

The os'nc macro starts a transaction that continues while the e!pressions in its body are evaluated. The ref-set function changes the in-transaction value of a Eef and returns it. $t must be called inside a transaction, otherwise an Ullegal%tate1Fception is thrown. The change will only be visible outside the transaction if and when the transaction commits. This happens when a os'nc e!its without an e!ception being thrown. For e!ample&
( os'nc

69

((( (ref-set name new-value) ((()

$f the new value must be computed from the old value then three steps are re#uired. :. deference the Eef to get the old value 5. compute the new value 4. set the new value The alter and commute functions perform these three steps as a single operation. The alter function is used for changes that must be made in a specific order. The commute function is used for changes whose order is not important ,i.e., commutative- and can be performed in parallel. ;ike ref-set, both must be called inside a transaction. Both take an *update function* that will compute the new value and additional arguments to be passed to it. This function will be passed the current in-transaction value of the Eef followed by the additional arguments, if any. =henever the new value is based on the old value ,computed as a function of the old value-, using alter or commute is preferred over ref-set. For e!ample, suppose we want to add one to the value of a Eef named counter. This could be implemented as follows, using inc for the update function&
( os'nc ((( (alter counter inc) ; or as (commute counter inc) ((()

$f an alter attempts to modify a Eef that has been changed by another thread since the current transaction began, the current transaction will retry from the beginning. Calls to commute do not do this. They proceed through the current transaction using in-transaction values for the Eefs. This results in better performance because retries aren%t performed. Eemember though that commute should only be used when the order of the updates they make across multiple transactions are not important. $f the transaction commits, something e!tra happens for the commute calls that were made in the transaction. For each commute call, the Eef they set will be reset using the result of the following call&
(appl' update-function last-committed-value-of-ref args)

Fote that the update function will be passed the last committed value of the Eef. This may be the result of a transaction that committed in another thread after the current transaction began. $t is not passed the in-transaction value of the Eef from the current transaction. )sing commute instead of alter is an optimi/ation. $t will not produce different end results unless the order of the updates really does matter.

68

;et%s walk through an e!ample that uses both Eefs and Atoms ,which are e!plained in more detail later-. This e!ample involves bank accounts and their transactions. First we%ll define the data model.
(ns com(ociwe$($an8) ; Dssume the onl' account ata that can change is its $alance( ( efstruct account-struct 7i 7owner 7$alance-ref) ; ; ; ; ( Ie nee to $e a$le to a an elete accounts to an Ie want it to $e sorte so we can easil' fin the highest account num$er for the purpose of assigning the neFt one( ef account-map-ref (ref (sorte -map))) from a map(

The following function creates a new account saves it in the account map, and returns it.
( efn open-account "creates a new account, stores it in the account map an returns it" ,owner( os'nc ; re5uire $ecause a 0ef is $eing change (let ,account-map =account-map-ref last-entr' (last account-map) ; Bhe i for the new account is one higher than the last one( i (if last-entr' (inc (8e' last-entr')) 1) ; *reate the new account with a Mero starting $alance( account (struct account-struct i owner (ref E)); D the new account to the map of accounts( (alter account-map-ref assoc i account) ; 0eturn the account that was +ust create ( account)))

The following functions support depositing and withdrawing money to and from an account.
( efn eposit ,account amount"a s mone' to an account; can $e a negative amount" ( os'nc ; re5uire $ecause a 0ef is $eing change (Bhrea "sleep PE) ; simulate a long-running operation (let ,owner (account 7owner) $alance-ref (account 7$alance-ref) t'pe (if (pos@ amount) " eposit" "with raw") irection (if (pos@ amount) "to" "from") a$s-amount (Rath"a$s amount)(if (>C (+ =$alance-ref amount) E) ; sufficient $alance@ ( o (alter $alance-ref + amount) (println (str t'pe "ing") a$s-amount irection owner)) (throw (UllegalDrgument1Fception( (str "insufficient $alance for " owner " to with raw " a$s-amount))))))) ( efn with "removes ,account ; D with ( eposit raw mone' from an account" amountrawal is li8e a negative account (- amount)))

eposit(

6N

The following function supports transferring money from one account to another. The transaction started by os'nc ensures that either both the withdrawal and the deposit occur or neither occurs.
( efn transfer ,from-account to-account amount( os'nc (println "transferring" amount "from" (from-account 7owner) "to" (to-account 7owner)) (with raw from-account amount) ( eposit to-account amount)))

The following functions support reporting on the state of accounts. The transaction started by os'nc ensures that the report will be consistent across accounts. For e!ample, it won%t report balances that are the result of a half-completed transfer.
( efn- report-1 ; a private function "prints information a$out a single account" ,account; Bhis assumes it is $eing calle from within ; the transaction starte in report( (let ,$alance-ref (account 7$alance-ref)(println "$alance for" (account 7owner) "is" =$alance-ref))) ( efn report "prints information a$out an' num$er of accounts" ,: accounts( os'nc ( ose5 ,account accounts- (report-1 account))))

This code doesn%t handle e!ceptions that occur within the threads it starts. $nstead we%ll define an e!ception handler for them in the current thread.
; %et a efault uncaught eFception han ler ; to han le eFceptions not caught in other threa s( (Bhrea "setVefaultWncaught1FceptionHan ler (proF' ,Bhrea LWncaught1FceptionHan ler- ,(uncaught1Fception ,threa throwa$le; #ust print the message in the eFception( (println ((( throwa$le (get*ause (getRessage)))))

Fow we%re ready to e!ercise the functions defined above.


(let ,a1 (open-account "Rar8") a2 (open-account "Bami") threa (Bhrea ( /(transfer a1 a2 PE))(tr' ( eposit a1 1EE) ( eposit a2 2EE) ; Bhere are sufficient fun s in Rar84s account at this point ; to transfer LPE to Bami4s account( ((start threa ) ; will sleep in eposit function twiceH ; Wnfortunatel', ue to the time it ta8es to complete the transfer ; (simulate with sleep calls), the neFt call will complete first( (with raw a1 OP)

67

; !ow there are insufficient fun s in Rar84s account ; to complete the transfer( ((+oin threa ) ; wait for threa to finish (report a1 a2) (catch UllegalDrgument1Fception e (println ((getRessage e) "in main threa "))))

The output from the code above is&


epositing 1EE to Rar8 epositing 2EE to Bami transferring PE from Rar8 to Bami with rawing OP from Rar8 transferring PE from Rar8 to Bami (a retr') insufficient $alance for Rar8 to with raw PE $alance for Rar8 is 2P $alance for Bami is 2EE

Validation Functions
Before moving on to discuss the ne!t reference type, here%s an e!ample of using a validation function to verify that all values assigned to a Eef are integers.
; !ote the use of the 7vali ator irective when creating the 0ef ; to assign a vali ation function which is integer@ in this case( ( ef m'-ref (ref E 7vali ator integer@)) (tr' ( os'nc (ref-set m'-ref 1) ; wor8s ; Bhe neFt line oesn4t wor8, so the transaction is rolle ; an the previous change isn4t committe ( (ref-set m'-ref "foo")) (catch Ullegal%tate1Fception e ; o nothing )) (println "m'-ref C" =m'-ref) ; ue to vali ation failure -> E $ac8

Atoms
Atoms provide a mechanism for updating a single value that is far simpler than the combination of Eefs and 1T>. They are not affected by transactions. There are three functions that change the value of an Atom, resetH, compare-an -setH and swapH. The resetH function takes the Atom to be set and the new value. $t sets the new value without considering the current value. For e!ample&
( ef m'-atom (atom 1)) (resetH m'-atom 2) (println =m'-atom) ; -> 2

DG

The compare-an -setH function takes the Atom to be set, what is believed to be the current value, and the desired new value. $f the current value matches the second argument then it is changed to the new value and true is returned. 0therwise the value remains unchanged and false is returned. This is useful to avoid changing the value if some other code has changed it since it was dereferenced at a particular point. The compare-an -setH function is typically used at the end of a section of code where the beginning is a binding that captures the dereferenced value of the Atom. The code in between can assume one of two outcomes. 0ne outcome is that the value of the Atom will remain unchanged while this code e!ecutes and compare-an -setH will change it at the end. The other outcome is that some other code will change the value of the Atom while this code e!ecutes and compare-an -setH will not change it at the end, returning false instead. For e!ample&
( ef m'-atom (atom 1)) ( efn up ate-atom ,(let ,curr-val =m'-atom(println "up ate-atom7 curr-val C" curr-val) ; -> 1 (Bhrea "sleep PE) ; give resetH time to run (println (compare-an -setH m'-atom curr-val (inc curr-val))))) ; -> false (let ,threa (Bhrea ( /(up ate-atom))((start threa ) (Bhrea "sleep 2P) ; give threa time to call up ate-atom (resetH m'-atom 3) ; happens after up ate-atom $in s curr-val ((+oin threa )) ; wait for threa to finish (println =m'-atom) ; -> 3

=hy is the output from this code 4J The up ate-atom function is called in a separate thread before the resetH function. $t captures the current value of the Atom which is :. Then it sleeps to give the resetH function time to run. After that, the value of the Atom is 4. =hen the up ate-atom function calls compare-an -setH to increment the value, it fails because the current value is no longer :. This means the value of the Atom remains set to 4. The swapH function takes an Atom to be set, a function to compute the new value and any number of additional arguments to be passed to the function. The function is called with the current value of the Atom and the additional arguments, if any. $t is essentially a wrapper around the use of compare-an -setH with one important difference. $t begins by dereferencing the Atom to save its current value. Fe!t, it calls the function to compute the new value. Finally, it calls compare-an -setH using the current value obtained at the beginning. $f compare-an -setH returns false, meaning the current value of the Atom didn%t match its value before the call to the function, the function is called repeatedl until this chec( succeeds. This is the important difference. The previous code can be written using swapH instead of compare-an -setH as follows&
( ef m'-atom (atom 1)) ( efn up ate-atom ,curr-val(println "up ate-atom7 curr-val C" curr-val) (Bhrea "sleep PE) ; give resetH time to run

D:

(inc curr-val)) (let ,threa (Bhrea ( /(swapH m'-atom up ate-atom))((start threa ) (Bhrea "sleep 2P) ; give swapH time to call up ate-atom (resetH m'-atom 3) ((+oin threa )) ; wait for threa to finish (println =m'-atom) ; -> K

=hy is the output from this code 6J The swapH function is called in a separate thread before the resetH function. =hen the up ate-atom function is called from swapH, the current value of the Atom is :. 3owever, due to the sleep call, it doesn%t complete before resetH is run, which sets the value to 4. The up ate-atom function returns 5. Before swapH can set the Atom to 5 it needs to verify that its current value is still :. $t isn%t, so swapH calls up ateatom again. This time the current value is 4, so it increments that and returns 6. The swapH function now successfully verifies that it knew the current value before the last call to up ate-atom and it sets the Atom to 6.

Agents
Agents are used to run tasks in separate threads that typically don%t re#uire coordination. They are useful for modifying the state of a single object which is the value of the agent. This value is changed by running an *action* in a separate thread. An action is a function that takes the current value of the Agent as its first argument and optionally takes additional arguments. !nl one action at a time $ill #e run on a given &gent) The agent function creates a new Agent. For e!ample&
( ef m'-agent (agent initial-value))

The sen function dispatches an action to an Agent and returns immediately instead of waiting for the action to complete. The action is e!ecuted in a thread from a supplied thread pool. =hen the action completes, its return value will be assigned to the Agent. The sen off function is similar, but uses threads from a different pool. The sen function uses a *fi!ed thread pool* ,see the newFi!edThread ool method in java.util.concurrent.?!ecutors- where the number of threads is the number of processors plus two. $f all of those threads are busy, the action doesn%t run until one becomes available. The sen -off function uses a *cached thread pool* ,see the newCachedThread ool method in java.util.concurrent.?!ecutors- where e!isting threads in the pool are used if available and new threads are added otherwise. $f the sen or sen -off functions are invoked from inside a transaction, the action isn%t actually sent until the transaction commits. This is somewhat similar to calling the commute function on a Eef in the sense that the calls that determine the value to retain occur at the end of the transaction. $nside actions, the Agent on which they are operating is bound to the symbol AagentA.

D5

The await function takes any number of Agents and blocks the current thread until all actions that thread has dispatched to those Agents have completed. The await-for function is similar, but takes a timeout in milliseconds as its first argument. $f the actions complete before the timeout occurs, it returns a non-nil value. 0therwise it returns nil. The await and await-for functions cannot be called inside a transaction. $f an action throws an e!ception then dereferencing the Agent to which it was sent will also throw an e!ception. The e!ceptions thrown in all actions that have been sent to a given Agent can be retrieved by calling the agent-errors function. The clear-agent-errors function clears the collection of e!ceptions for a given Agent. The shut own-agents function waits for the e!ecution of all actions already sent to all Agents to complete. $t then stops all the threads in the thread pools that are used by Agents. After this has been called, no new actions can be sent. Calling shut own-agents is necessary to allow the 2A> to e!it in an orderly manner because the threads in the Agent thread pools are not daemon threads.

atchers
=AEF$FH& This section needs to be updated for changes made in Clojure :.:. The a watcher and remove-watcher function have been removed. The a -watch and removewatch functions, that works differently, have been added. Agents can act as watchers of other reference type objects. After the value of a watched reference has changed, the Agent is notified by sending it an action. The type of the send, sen or sen -off, is specified when the watcher is registered with a reference object. The action function is passed the current value of the Agent ,not the value of the reference object that changed- and the reference object whose state changed. The return value of the action function becomes the new value of the Agent. As stated earlier, functional programming emphasi/es the use of *pure functions* which have no side effects such as changing global state. Clojure doesn%t prevent functions from doing this, but it does make it easy to find the functions that do. 0ne way is to search the source code for functions and macros that call any of the small set of functions that change global state ,for e!ample, alter-. Another way is to use watchers to detect changes. A watcher could print a stack trace to identify the function that made the change. The e!ample below registers a watcher Agent with a Aar, a Eef and an Atom. The state of the watcher Agent is a map that is used to count the number of times each reference it is watching changes. The keys in this map are the reference objects and the values are change counts.
( ef m'-watcher (agent &))) ( efn m'-watcher-action ,current-value reference(let ,change-count-map current-value ol -count (change-count-map reference) new-count (if ol -count (inc ol -count) 1); 0eturn an up ate map of change counts ; that will $ecome the new value of the Dgent( (assoc change-count-map reference new-count)))

D4

( ef m'-var "v1") ( ef m'-ref (ref "r1")) ( ef m'-atom (atom "a1")) (a (a (a -watcher (var m'-var) 7sen -off m'-watcher m'-watcher-action) -watcher m'-ref 7sen -off m'-watcher m'-watcher-action) -watcher m'-atom 7sen -off m'-watcher m'-watcher-action)

; *hange the root $in ing of the >ar in two wa's( ( ef m'-var "v2") (alter-var-root (var m'-var) (fn ,curr-val- "v3")) ; *hange the 0ef in two wa's( ( os'nc ; Bhe neFt line onl' changes the in-transaction value ; so the watcher isn4t notifie ( (ref-set m'-ref "r2") ; Ihen the transaction commits, the watcher is ; notifie of one change this 0ef ((( the last one( (ref-set m'-ref "r3")) ( os'nc (alter m'-ref (fn ,;- "rK"))) ; Dn now one more( ; *hange the Dtom in two wa's( (resetH m'-atom "a2") (compare-an -setH m'-atom =m'-atom "a3") ; Iait for all the actions sent to the watcher Dgent to complete( (await m'-watcher) ; Gutput the num$er of changes to ; each reference o$+ect that was watche ( (let ,change-count-map =m'-watcher(println "m'-var changes C" (change-count-map (var m'-var))) ; -> 2 (println "m'-ref changes C" (change-count-map m'-ref)) ; -> 2 (println "m'-atom changes C" (change-count-map m'-atom))) ; -> 2 (shut own-agents)

Com!iling
=hen Clojure source files are e!ecuted as scripts, they are compiled to 2ava bytecode at runtime. They can also be compiled to 2ava bytecode ahead of time ,A0T-. This improves the startup time of Clojure applications and produces .class files that can be used in 2ava applications. Eecommended steps to do this are& :. 1elect a namespace for the source files to be compiled, for e!ample, com(ociwe$(tal8. 5. Create directories named *src* and *classes* in the same parent directory. 4. >ake one of the source files have the same name as the last part of the namespace. =e%ll call this the main source file. For e!ample, tal8(cl+. 6. lace the source files under the *src* directory in a directory structure patterned after the namespace. For e!ample, the main source would be src"com"ociwe$"tal8(cl+. D. 1pecify the namespace at the top of the main source file and include the 7gen-class namespace directive. For e!ample& (ns com(ociwe$(tal8 (7gen-class))

D6

9. $n the main source file, use the loa function to load all the other source files in the same namespace with relative paths. For e!ample, if the file more(cl+ is in a subdirectory of src"com"ociwe$ named *tal8*, use (loa "tal8"more"). 8. $n each of the other source files, use the in-ns function to set their namespace. For e!ample, add (in-ns 4com(ociwe$(tal8) to the top of more(cl+. N. Add the *src* and *classes* directories to the classpath used by the E? ;. $f a script is used to run the E? ;, modify that script. 7. 1tart a E? ;. :G. )se the compile function to compile all the source files in a given namespace by entering (compile 4namespace). For e!ample& (compile 4com(ociwe$(tal8). A separate .class file is produced for each function. They are written under the *classes* directory in a directory structure that corresponds to their namespace. $f the compiled namespace has a function named -main, it can be run as a 2ava application. Command-line arguments are passed as arguments to that function. For e!ample, if tal8(cl+ contained a -main function, it could be run as follows&
+ava -classpath path"classes7path"clo+ure(+ar com(ociwe$(tal8 args

!a"a Calling Clo#ure


A0T compiled Clojure functions can be called from a 2ava application if they are marked as static. To do this, set the metadata key 7static to true in the 7gen-class 7metho s directive. The 7metho s directive also specifies the 2ava types for the parameters and return value. The synta! for this is&
(ns namespace (7gen-class 7metho s ,9&7static true) ,function-name ,param-types- return-type--))

;et%s walk through an e!ample. 3ere%s a Clojure source file named Vemo(cl+ in the directory src"com"ociwe$"cl+.
(ns com(ociwe$(cl+(Vemo (7gen-class 7metho s ,9&7static true) ,getRessage ,%tring- %tring--)) / !ote the h'phen at the $eginning of the function nameH ( efn -getRessage ,name(str "Hello, " name "H"))

3ere%s a 2ava source file named Rain(+ava that is in the same directory as the src and classes directories.
import com(ociwe$(cl+(Vemo; "" class create file pu$lic class Rain & pu$lic static voi main(%tring,- args) & %tring message C Vemo(getRessage("Rar8"); %'stem(out(println(message); $' compiling *lo+ure source

DD

3ere are the steps to build and run it. :. 5. 4. 6. D. cd to the directory containing the src and classes directories. 1tart a E? ; by entering *cl+*. ?nter *(compile 4com(ociwe$(cl+(Vemo)*. ?!it the E? ; ,ctrl-d or ctrl-c-. ?nter *+avap -classpath classes com(ociwe$(cl+(Vemo* to see the methods in the generated class. 9. ?nter *+avac -cp classes Rain(+ava*. 8. ?nter *+ava -cp (7classes7path"clo+ure(+ar Rain(+ava*. )se semicolons instead of colons under =indows. N. The output should be *Hello, Rar8H*. There are many more advanced compiling features. For more detail, see the A $ documentation for the gen-class macro. Also see http&++clojure.org+compilation+.

*utomated )esting
The primary automated testing framework for Clojure is the test library included in Clojure core. The following code demonstrates its main features&
(use 4clo+ure(test) ; Bests can $e written in separate functions( ( eftest a -test ; Bhe "is" macro ta8es a pre icate, arguments to it, ; an an optional message( (is (C K (+ 2 2))) (is (C 2 (+ 2 E)) "a ing Mero oesn4t change value")) ( eftest reverse-test (is (C ,3 2 1- (reverse ,1 2 3-)))) ; Bests can verif' that a specific eFception is thrown( ( eftest ivision-test (is (thrown@ Drithmetic1Fception (" 3(E E)))) ; Bhe with-test macro can $e ; to the functions the' test (with-test ( efn m'-a ,n1 n2- (+ n1 (is (C K (m'-a 2 2))) (is (C 2 (m'-a 2 E)) "a ; ; ; ; ( use to a tests as meta ata( n2)) ing Mero oesn4t change value"))

Bhe "are" macro ta8es a pre icate template an multiple sets of arguments to it, $ut no message( 1ach set of arguments are su$stitute one at a time into the pre icate template an evaluate ( eftest multiplication (are ,n1 n2 result(C (A n1 n2) result) ; a template 1 1 1, 1 2 2,

D9

2 3 J)) ; 0un all the tests in the current namespace( ; Bhis inclu es tests that were a e as function meta ata using with-test( ; Gther namespaces can $e specifie as 5uote arguments( (run-tests)

To limit the depth of stack traces that are output when an e!ception is thrown from a test, bind the special symbol Astac8-trace- epthA to an integer depth. =hen A0T compiling Clojure code to bytecode for production use, bind the Aloa -testsA symbol to false to avoid compiling test code. =hile not on the same level as automated testing, Clojure provides an assert macro. $t takes an e!pression, evaluates it and throws an e!ception if it evaluates to false. This is useful for catching conditions that should never occur. For e!ample&
(assert (>C ow OEEE))

Another important feature of the test library is fi!tures. They are code that wraps the e!ecution of test methods. Fi!tures come in two varieties, those that wrap the e!ecution of each test method and those that wrap the e!ecution of the entire run of test methods. To create a fi!ture, write a function that follows this pattern&
( efn fiFture-name ,test-function; 2erform setup here( (test-function) ; 2erform tear own here( )

The fi!ture function will be called once for each test function. The value of the testfunction parameter will be the current function to be e!ecuted. To register fi!tures to wrap each test method&
(use-fiFtures 7each fiFture-1 fiFture-2 ((()

The order of e!ecution will be& :. 5. 4. 6. D. fi!ture-: setup fi!ture-5 setup 0F? test function fi!ture-5 teardown fi!ture-: teardown

To register fi!tures to wrap the entire run&


(use-fiFtures 7once fiFture-1 fiFture-2 ((()

The order of e!ecution will be&

D8

:. 5. 4. 6. D.

fi!ture-: setup fi!ture-5 setup A;; test functions fi!ture-5 teardown fi!ture-: teardown

Clojure ships with its own suite of tests in its test subdirectory. To run them, cd to the directory containing the Clojure src and test directories and enter *ant test*.

Editors and I"Es


Clojure plugins for many editors and $<?s are available. For emacs there is clojure-mode and swank-clojure, both at https&++github.com+technomancy+swank-clojure. swank-clojure uses the 1uperior ;isp $nteraction >ode for ?macs ,1lime- described at http&++commonlisp.net+project+slime+. For Aim there is AimClojure at http&++www.vim.org+scripts+script.phpJ scriptSidQ5DG:. For FetBeans there is enclojure at http&++enclojure.org+. For $<?A there a *;a Clojure* at http&++plugins.intellij.net+plugin+JidQ6GDG. For ?clipse there is Counter Clockwise at http&++dev.clojure.org+display+doc+HettingL1tartedLwithL?clipseLandLCounterclockwise.

"es+to! *!!lications
Clojure can be used to create 1wing-based H)$ applications. 3ere%s a simple e!ample that allows the user to enter their name, press a *Hreet* button, and receive a greeting in a dialog. Fote the use of the proF' macro to create a 2ava object that e!tends a given 2ava class ,#Yrame in this case- and+or implements any number of 2ava interfaces ,only Dction3istener in this case-.

DN

(ns com(ociwe$(swing (7import (+ava(awt Tor er3a'out) (+ava(awt(event Dction3istener) (+avaF(swing #Tutton #Yrame #3a$el #Gption2ane #2anel #BeFtYiel ))) ( efn message "gets the message to ispla' $ase on the current teFt in teFt-fiel " ,teFt-fiel (str "Hello, " ((getBeFt teFt-fiel ) "H")) ; %et the initial teFt in name-fiel to "Iorl " ; an its visi$le wi th to 1E( (let ,name-fiel (#BeFtYiel ( "Iorl " 1E) greet-$utton (#Tutton( "Sreet") panel (#2anel() frame (proF' ,#Yrame Dction3istener,- ; superclass constructor arguments (action2erforme ,e- ; nil $elow is the parent component (#Gption2ane"showRessageVialog nil (message name-fiel ))))( oto panel ((a (#3a$el( "!ame7")) ((a name-fiel )) ( oto frame ((a panel Tor er3a'out"*1!B10) ((a greet-$utton Tor er3a'out"%GWBH) ((pac8) ((setVefault*loseGperation #Yrame"1]UB;G!;*3G%1) ((set>isi$le true)) ; 0egister frame to listen for greet-$utton presses( ((a Dction3istener greet-$utton frame))

,e% *!!lications
There are several Clojure libraries for creating web applications. A popular choice these days is Foir by Chris Hranger. A simple, convention-based >AC framework, that uses Christophe Hrand%s ?nlive for view templates, is Framework 0ne by 1ean Corfield. Another popular choice is Compojure by 2ames Eeeves which can be downloaded from http&++github.com+weavejester+compojure+tree+master. All of these web frameworks are based on Eing by >ark >cHranahan and maintained by 2ames Eeeves. =e%re going to look at Compojure as an e!ample. The latest version can be retrieved from a Hit repository as follows ,assuming Hit is already installed-&
git clone git7""githu$(com"weave+ester"compo+ure(git

This creates a directory named compo+ure in the current directory. Additional 2AEs must be downloaded from http&++cloud.github.com+downloads+weavejester+compojure+deps./ip. lace eps(Mip in the compo+ure directory and un/ip it to create a eps subdirectory. To build compo+ure(+ar, run ant from the compojure directory. To get updates to Compojure, cd to the compo+ure directory and run the following commands&
git pull ant clean eps +ar

D7

All the 2AE files in the eps subdirectory must be in the classpath. 0ne way to achieve this is to modify the cl+ script and use it to run the web application. Add *-cp L*2* to the +ava command used to run clo+ure(main and add the following lines ,which are )F$(-specificbefore that to set *2.
/ %et *2 to a path list that contains clo+ure(+ar / an possi$l' some *lo+ure contri$ #D0 files( *GR2G#W01;VU0Cpath-to-compojure-dir *GR2G#W01;#D0CL*GR2G#W01;VU0"compo+ure(+ar *2CL*27L*GR2G#W01;#D0 for file in L*GR2G#W01;VU0" eps"A(+ar o *2CL*27Lfile one

3ere%s an e!ample of a simple Compojure web application.

(ns com(ociwe$(hello (7use compo+ure)) ( ( ( ( ef ef ef ef host "localhost") port QEQE) in-path ""hello") out-path ""hello-out") $o ' content"

( efn html- oc "generates well-forme HBR3 for a given title an ,title : $o '(html ( oct'pe 7htmlK) ,7html ,7hea ,7title title-,7$o ' $o '--)) ; *reates HBR3 for input form( ( ef hello-in (html- oc "Hello Un" (form-to ,7post out-path"!ame7 " (teFt-fiel &7siMe 1E) 7name "Iorl ") ,7$r(reset-$utton "0eset") (su$mit-$utton "Sreet")))) ; *reates HBR3 for result message( ( efn hello-out ,name(html- oc "Hello Gut" ,7h1 "Hello, " name "H"-)) ( efroutes hello-service ; Bhe following three lines map HBB2 metho s ; an W03 patterns to response HBR3( (S1B in-path hello-in) (2G%B out-path (hello-out (params 7name)))

9G

(D![ "A" (page-not-foun ))) ;

ispla's ("pu$lic"KEK(html $'

efault

(println (str "$rowse http7""" host "7" port in-path)) ; -> $rowse http7""localhost7QEQE"hello (run-server &7port port) ""A" (servlet hello-service))

"ata%ases
The jdbc library in Clojure Contrib simplifies accessing relational databases. $t supports transactions with commit and rollback, prepared statements, creating+dropping tables, inserting+updating+deleting rows, and running #ueries. The following e!ample connects to a ostgres database and runs a #uery. Aalues to use for a >y1T; database are provided in comments after the ostgres values.
(use 4clo+ure(+ava(+ $c) (let , $-host "localhost" $-port PK32 ; 33EJ $-name "H0"; Bhe classname $elow must $e in the classpath( ( ef $ &7classname "org(postgres5l(Vriver" ; com(m's5l(+ $c(Vriver 7su$protocol "postgres5l" ; "m's5l" 7su$name (str """" $-host "7" $-port """ $-name) ; Dn' a itional map entries are passe to the river ; as river-specific properties( 7user "mvol8mann" 7passwor "cl+fan")) (with-connection $ ; closes connection when finishe (with-5uer'-results rs ,"select A from 1mplo'ee"- ; closes result set when finishe ; rs will $e a non-laM' se5uence of maps, ; one for each recor in the result set( ; Bhe 8e's in each map are the column names retrieve an ; their values are the column values for that result set row( ( ose5 ,row rs- (println (row 7lastname))))))

The cl+-recor library provides a persistence A $ that is inspired by the Euby on Eails ActiveEecord library. For more information, browse http&++github.com+duelinmarkers+cljrecord+tree+master.

Li%raries
>any libraries of Clojure functions and macros that support capabilities beyond what is in Clojure proper have been contributed and are part of Clojure Contrib. 1ome of these that were not discussed earlier are summari/ed below. $n addition, many of the known libraries are described at http&++clojure.org+libraries.

clojure.tools.cli - processes command-line arguments and outputs help clojure.data.!ml - performs la/y parsing of (>; clojure.algo.monads - provides commonly used monads, monad transformers, and macros for defining and using monads clojure.java.shell - provides functions and macros for launching subprocesses and controlling their stdin+stdout 9:

clojure.stacktrace - provides functions that simplify stack trace output by focusing on Clojure-specific content clojure.string - provides functions for working with strings and regular e!pressions clojure.tools.trace - provides tracing output for all calls to a given function and returns from it

3ere%s a brief e!ample of using clojure.java.shell to obtain the *print working directory*.
(use 4clo+ure(+ava(shell) ( ef irector' (sh "pw "))

Conclusion
This article has covered a lot of ground. $f you%re hungry for more, a great source is the book * rogramming Clojure* written by 1tuart 3alloway. This article focuses on the features of Clojure :.G and will be updated by various community members over time. For a review of the changes in Clojure :.: and beyond, see http&++www.fogus.me+static+preso+clj:.:L+. 3ere are some key #uestions to ask yourself that will help in deciding whether you should give Clojure a try.

Are you looking for a way to make concurrent programming easierJ Are you open to branching outside the world of object-oriented programming to try functional programmingJ $s it important for the applications you write to run on the 2A> in order to take advantage of e!isting 2ava libraries, portability and other benefitsJ <o you prefer dynamically-typed languages over statically-typed onesJ <o you find the minimal, consistent synta! of ;isp dialects appealingJ

$f you answered *yes* to some of these #uestions then you should consider using Clojure as your ne!t programming language.

Re#erences

my Clojure site - http&++www.ociweb.com+mark+clojure+ my 1T> site - http&++www.ociweb.com+mark+stm+ Clojure main site - http&++clojure.org+ Clojure A $ - http&++clojure.github.com+api-inde!.html Clojure <ocumentation - http&++clojure-doc.org+ Clojure<ocs - http&++clojuredocs.org+ Clojure Atlas - http&++www.clojureatlas.com+ Clojure class diagram - http&++github.com+Chouser+clojure-classes+tree+master+graphw-legend.png =ikibooks Clojure rogramming http&++en.wikibooks.org+wiki+ClojureS rogramming =ikibooks ;earning Clojure - http&++en.wikibooks.org+wiki+;earningSClojure =ikibooks Clojure A $ ?!amples http&++en.wikibooks.org+wiki+ClojureS rogramming+?!amples+A $S?!amples

95

roject ?uler Clojure code - http&++clojure-euler.wikispaces.com+ >odular contrib documentation http&++dev.clojure.org+display+design+=hereL<idLClojure.ContribLHo Clojure 1nake Hame http&++www.ociweb.com+mark+programming+Clojure1nake.html

94

Вам также может понравиться