Clojure Programming/Concepts

Types of Numbers
Clojure supports the following numeric types:


 * Integer
 * Floating Point
 * Ratio
 * Decimal

Numbers in Clojure are based on java.lang.Number. BigInteger and BigDecimal are supported and hence we have arbitrary precision numbers in Clojure.

The Ratio type is described on Clojure page as


 * Ratio
 * Represents a ratio between integers. Division of integers that can't be reduced to an integer yields a ratio, i.e. 22/7 = 22/7, rather than a floating point or truncated value.

Ratios allows a computation to be maintained in numeric form. This can help avoid inaccuracies in long computations.

Here is a little experiment. Lets first try a computation of  as floating point. Later we try the same with Ratio.

The result we want is, but the value of   above is. This is due to the inaccuracies of a and b multiplying as we create c and d. You really don't want such calculations happening in your pay cheque :)

The same done with ratios below:

The result is  as we hoped for.

Number Entry Formats
Clojure supports the usual formats for entry as shown below

To make things easier, a radix based entry format is also supported in the form. Where radix can be any natural number between 2 and 36.

These formats can be mixed and used.

Many bitwise operations are also supported by Clojure API:

Some of the others are:
 * (bit-and x y)
 * (bit-and-not x y)
 * (bit-clear x n)
 * (bit-flip x n)
 * (bit-not x)
 * (bit-or x y)
 * (bit-set x n)
 * (bit-shift-left x n)
 * (bit-shift-right x n)
 * (bit-test x n)
 * (bit-xor x y)

Check Clojure API for the complete documentation.

Converting Integers to Strings
One general purpose way to format any data for printing is to use a java.util.Formatter.

The predefined convenience function  makes using a Formatter easy (the hash in   displays the number as a hexadecimal number prefixed with  ):

Converting integers to strings is even easier with java.lang.Integer. Note that since the methods are static, we must use the "/" syntax instead of ".method":

Here is another way to specify the base of the string representation:

Where 10 is the number to be converted and 2 is the radix.

Note: In addition to the above syntax, which is used for accessing static fields or methods,  can be used. It is a special form used for accessing arbitrary (non-private) fields or methods in Java as explained in the Clojure Reference (Java Interop). For example:

For static accesses, the / syntax is preferred.

Converting Strings to Integers
For converting strings to integers, we can again use java.lang.Integer. This is shown below.

user=> (Integer/parseInt "A" 16)     ; hex 10   user=> (Integer/parseInt "1010" 2)    ; bin 10   user=> (Integer/parseInt "10" 8)      ; oct 8   user=> (Integer/parseInt "8")         ; dec 8

The above sections give an overview of the integer-to-string and string-to-integer formatting. There is a very rich set of well documented functions available in the Java libraries (too rich to document here). These functions can easily be used to meet varied needs.

Structures
Structures in Clojure are a little different from those in languages like Java or C++. They are also different from structures in Common Lisp (even though we have a  in Clojure).

In Clojure, structures are a special case of maps and are explained in the data structures section in the reference.

The idea is that multiple instance of the structures will need to access their field values using the field names which are basically the map keys. This is fast and convenient, especially because Clojure automatically defines the keys as accessors for the structure instances.

Following are the important functions dealing with structures: For the full API refer to data structures section in Clojure reference.
 * defstruct
 * create-struct
 * struct
 * struct-map

Structures are created using  which is a macro wrapping the function  which actually creates the struct. creates the structure using and binds it to the structure name supplied to.

The object returned by  is what is called the structure basis. This is not a structure instance but contains information of what the structure instances should look like. New instances are created using  or.

The structure field names of type keyword or symbols are automatically usable as functions to access fields of the structure. This is possible as structures are maps and this feature is supported by maps. This is ''not possible for other types'' of field names such as strings or numbers. It is quite common to use keywords for field names for structures due to the above reason. Also, Clojure optimises structures to share base key information. The following shows sample usage:

Clojure also supports the  function that can be used to get accessor functions for fields to allow easy access. This is important when field names are of types other than keyword or symbols. This is seen in the interaction below.

As structures are maps, new fields can be added to structure instances using .  can be used to remove these instance specific keys. Note however that struct base keys cannot be removed.

can also be used to "update" a structure.

Observe that like other sequences in Clojure, structures are also immutable, hence, simply doing  above does not change . Hence we rebind it to. While it is possible to rebind the new value back to, this is not considered good style.

Exception Handling
Clojure supports Java based Exceptions. This may need some getting used to for Common Lisp users who are used to the Common Lisp Condition System.

Clojure does not support a condition system and is not expected to be supported anytime soon as per this message. That said, the more common exception system which is adopted by Clojure is well suited for most programming needs.

If you are new to exception handling, the Java Tutorial on Exceptions is a good place to learn about them.

In Clojure, exceptions can be handled using the following functions:
 * catch-clause -> (catch classname name expr*)
 * finally-clause -> (finally expr*)
 * finally-clause -> (finally expr*)

Two types of exceptions you may want to handle in Clojure are:
 * Clojure Exception: These are exception generated by Clojure or the underlying Java engine
 * User Defined Exception: These are exceptions which you might create for your applications

Clojure Exceptions
Below is a simple interaction at the REPL that throws an exception:

In the above case we see a  being thrown. This is a runtime exception which is thrown by the underlying JVM. The long message can sometimes be intimidating for new users but the trick is to simply look at the exception and not bother with the rest of the trace.

Similar exceptions may be thrown by the compiler at the REPL. In the above case, the compiler does not find the binding for   and hence it throws the exception. If your program is correct (i.e. in this case  is defined  ), you won't see any compile time exceptions.

The following interaction shows how runtime exceptions like  can be handled.

The syntax for the  block is.

As can be seen, it's quite easy to handle exceptions in Clojure. One thing to note is that  is a catch all for exceptions as   is a superclass of all exceptions. It is also possible to catch specific exceptions which is generally a good idea.

In the example below, we specifically catch.

When we use some other exception type in the catch block, we find that the  is not caught and is seen by the REPL.

User-Defined Exceptions
As mentioned previously, all exceptions in Clojure need to be a subclass of java.lang.Exception (or generally speaking - java.lang.Throwable which is the superclass for Exception). This means that even when you want to define your own exceptions in Clojure, you need to derive it from Exception.

Don't worry, that's easier than it sounds :)

Clojure API provides a function  which can be used to extend   for user-defined exceptions. generates and immediately loads the bytecode for the specified class.

Now, rather than talking too much, let's quickly look at code.

Here we are creating a new class  that extends. We create an instance of  using the special form. This is then thrown.

Sometimes you may come across code like. This is just another way to say. Note the  after the. This does exactly the same thing.

Here is the interaction: user=> (load-file "except.clj")
 * 1) 'user/user-exception-test

user=> (user-exception-test) "caught exception" user.UserException: msg: user exception was here!! "finally clause invoked!!!" nil user=>

So here we have both the  and the clauses being invoked. That's all there is to it.

With Clojure's support for Java Interop, it is also possible for the user to create exceptions in Java and catch them in Clojure, but creating the exception in Clojure is typically more convenient.

Employee Record Manipulation
Data structures and sequences in Clojure are immutable as seen in the examples presented in Clojure_Programming/Concepts (it is suggested that the reader go through that section first).

While immutable data has its advantages, any project of reasonable size will require the programmer to maintain some sort of state. Managing state in a language with immutable sequences and data structures is a frequent source of confusion for people used to programming languages that allow mutation of data.

A good essay on the Clojure approach is Values and Change - Clojure's approach to Identity and State, written by Rich Hickey.

It may be useful to watch Clojure Concurrency screen cast as some of those concepts are used in this section. Specifically refs and transactions.

In this section we create a simple employee record set and provide functions to:
 * Add an employee
 * Delete employee by name
 * Change employee role by name

The example is purposely kept simple as the intent is to show the state and mutation facilities rather than provide full functionality.

Lets dive into the code.

In the first few lines we define the  structure. The interesting definition after that is.

In Clojure refs allow mutation of a storage location with a transaction.

user=> (def x (ref [1 2 3])) user=> x clojure.lang.Ref@128594c user=> @x [1 2 3] user=> (deref x) [1 2 3] user=>
 * 1) 'user/x

Next we define private functions  and   using   (note the minus '-' at the end). Observe that these are pure functions without any side-effects.

takes the employee name, the new role   and a table of employee records. As sequences are immutable, this function returns a new table of records with the employee role updated appropriately. also behaves in a similar manner by returning a new table of employees after deleting the relevant employee record.

For an explanation of the  API see Clojure API reference.

We still haven't looked at how state is maintained. This is done by the public functions in the listing,   and.

These functions delegate the job of record processing to the private functions. The important things to note are the use of the following functions: For a detailed explanation of these functions see the refs section in API reference.
 * sets the value of a ref.
 * is mandatory as refs can only be updated in a transaction and  sets up the transaction.
 * updates the in-transaction value of a ref.

The  function is quite trivial and hence not broken up into private and public function.

The source listing initializes the records with sample data towards the end.

Below is the interaction for this program. user=> (load-file "employee.clj")
 * {{:name "Jack", :id 0, :role :Engineer} {:name "Hill", :id 2, :role :Stand} {:name "Jill", :id 1, :role :Finance}}

user=> @employee-records
 * {{:name "Jack", :id 0, :role :Engineer} {:name "Hill", :id 2, :role :Stand} {:name "Jill", :id 1, :role :Finance}}

user=> (add-employee (struct employee "James" 3 :Bond)) user=> @employee-records
 * {{:name "James", :id 3, :role :Bond} {:name "Jack", :id 0, :role :Engineer} {:name "Hill", :id 2, :role :Stand} {:name "Jill", :id 1, :role :Finance}}
 * {{:name "James", :id 3, :role :Bond} {:name "Jack", :id 0, :role :Engineer} {:name "Hill", :id 2, :role :Stand} {:name "Jill", :id 1, :role :Finance}}

user=> (update-employee-role "Jill" :Sr.Finance) user=> @employee-records
 * {{:name "James", :id 3, :role :Bond} {:name "Jack", :id 0, :role :Engineer} {:name "Hill", :id 2, :role :Stand} {:name "Jill", :id 1, :role :Sr.Finance}}
 * {{:name "James", :id 3, :role :Bond} {:name "Jack", :id 0, :role :Engineer} {:name "Hill", :id 2, :role :Stand} {:name "Jill", :id 1, :role :Sr.Finance}}

user=> (delete-employee-by-name "Hill") user=> @employee-records
 * {{:name "James", :id 3, :role :Bond} {:name "Jack", :id 0, :role :Engineer} {:name "Jill", :id 1, :role :Sr.Finance}}
 * {{:name "James", :id 3, :role :Bond} {:name "Jack", :id 0, :role :Engineer} {:name "Jill", :id 1, :role :Sr.Finance}}

Two things to note about the program:
 * Using refs and transactions makes the program inherently thread safe. If we want to extend the program for a multi-threaded environment (using Clojure agents) it will scale with minimal change.
 * Keeping the pure functionality separate from the public function that manages state, it is easier to ensure that the functionality is correct as pure functions are easier to test.

Overview

 * use  to load clojure libraries
 * use  to refer to functions in the current namespace
 * use  to load and refer all in one step
 * use  to refer to Java classes in the current namespace

Require

1. You can load the code for any clojure library with  libname. Try it with : (require clojure.contrib.math) 2. Then print the directory of names available in the namespace (dir clojure.contrib.math) 3. Show using  to calculate the least common multiple: 1	(clojure.contrib.math/lcm 11 41) 2	-> 451 4. Writing out the namespace prefix on every function call is a pain, so you can specify a shorter alias using : (require [clojure.contrib.math :as m]) 5. Calling the shorter form is much easier: 1	(m/lcm 120 1000) 2	-> 3000 6. You can see all the loaded namespaces with (all-ns)

Refer and Use
1. It would be even easier to use a function with no namespace prefix at all. You can do this by referring to the name, which makes a reference to the name in the current namespace: (refer 'clojure.contrib.math) 2. Now you can call  directly: 1	(lcm 16 30) 2	-> 240 3. If you want to load and refer all in one step, call : (use 'clojure.contrib.math) 4. Referring a library refers all of its names. This is often undesirable, because Instead, use the following style to specify only those names you want: (use '[clojure.contrib.math :only (lcm)]) The  option is available on all the namespace management forms. (There is also an  which works as you might expect.)
 * it does not clearly document intent to readers
 * it brings in more names than you need, which can lead to name collisions

5. The variable  always contains the current namespace, and you can see what names your current namespace refers to by calling (ns-refers *ns*) 6. The refers map is often pretty big. If you are only interested in one symbol, pass that symbol to the result of calling : 1	((ns-refers *ns*) 'dir) 2	-> #'clojure.contrib.ns-utils/dir

Import
1. Importing is like referring, but for Java classes instead of Clojure namespaces. Instead of     (java.io.File. "woozle") you can say 1	(import java.io.File) 2	(File. "woozle") 2. You can import multiple classes in a Java package with the form (import [package Class Class]) For example: 1	(import [java.util Date Random]) 2	(Date. (long (.nextInt (Random.)))) 3. Programmers new to Lisp are often put off by the "inside-out" reading of forms like the date creation above. Starting from the inside, you You don't have to write inside-out code in Clojure. The -> macro takes its first form, and passes it as the first argument to its next form. The result then becomes the first argument of the next form, and so on. It is easier to read than to describe: 1	(-> (Random.) (.nextInt) (long) (Date.)) 2	-> #
 * get a new Random
 * get the next random integer
 * cast it to a long
 * pass the long to the Date constructor

Load and Reload
The REPL isn't for everything. For work you plan to keep, you will want to place your source code in a separate file. Here are the rules of thumb to remember when creating your own Clojure namespaces.

1. Clojure namespaces (a.k.a. libraries) are equivalent to Java packages.

2. Clojure respects Java naming conventions for directories and files, but Lisp naming conventions for namespace names. So a Clojure namespace com.my-app.utils would live in a path named com/my_app/utils.clj. Note especially the underscore/hyphen distinction.

3. Clojure files normally begin with a namespace declaration, e.g.     (ns com.my-app.utils)

4. The syntax for import/use/refer/require presented in the previous sections is for REPL use. Namespace declarations allow similar forms&mdash;similar enough to aid memory, but also different enough to confuse. The following forms at the REPL: 1	(use 'foo.bar) 2	(require 'baz.quux) 3	(import '[java.util Date Random]) would look like this in a source code file: 1	(ns     2	 com.my-app.utils      3	 (:use foo.bar)      4	 (:require baz.quux)      5	 (:import [java.util Date Random])) Symbols become keywords, and quoting is no longer required.

5. At the time of this writing, the error messages for doing it wrong with namespaces are, well, opaque. Be careful.

Now let's try creating a source code file. We aren't going to bother with explicit compilation for now. Clojure will automatically (and quickly) compile source code files on the classpath. Instead, we can just add Clojure (.clj) files to the src directory.

1. Create a file named student/dialect.clj in the src directory, with the appropriate namespace declaration: (ns student.dialect) 2. Now, implement a simple canadianize function that takes a string, and appends, eh? (defn canadianize [sentence] (str sentence ", eh")) 3. From your REPL, use the new namespace: (use 'student.dialect) 4. Now try it out. 1	(canadianize "Hello, world.") 2	-> "Hello, world., eh" 5. Oops! We need to trim the period off the end of the input. Fortunately, clojure.contrib.str-utils2 provides chop. Go back to student/dialect.clj and add require in clojure.contrib.str-utils2: (ns student.dialect (:require [clojure.contrib.str-utils2 :as s])) 6. Now, update canadianize to use chop: (defn canadianize [sentence] (str (s/chop sentence) ", eh?")) 7. If you simply retry calling canadianize from the repl, you will not see your new change, because the code was already loaded. However, you can use namespace forms with reload ( or reload-all) to reload a namespace (and its dependencies). (use :reload 'student.dialect) 8. Now you should see the new version of canadianize: 1	(canadianize "Hello, world.") 2	-> "Hello, world, eh?"

Anonymous Functions
Clojure supports anonymous functions using  or the shorter reader macro. The  is convenient due to its conciseness but is somewhat limited as   form cannot be nested.

Below are some examples using both forms: user=> ((fn [x] (* x x)) 3) 9

user=> (map #(list %1 (inc %2)) [1 2 3] [1 2 3]) ((1 2) (2 3) (3 4))

user=> (map (fn [x y] (list x (inc y))) [1 2 3] [1 2 3]) ((1 2) (2 3) (3 4))

user=> (map #(list % (inc %)) [1 2 3]) ((1 2) (2 3) (3 4))

user=> (map (fn [x] (list x (inc x))) [1 2 3]) ((1 2) (2 3) (3 4))

user=> (#(apply str %&) "Hello") "Hello"

user=> (#(apply str %&) "Hello" ", " "World!") "Hello, World!"

Note that in  form,   is used for arguments (1 based) and   for the rest argument. is a synonym for.

Lazy Evaluation of Sequences
This section tries to walk through some code to give a better feel for the lazy evaluation of sequences by Clojure and how that might be useful. We also measure memory and time to understand whats happening better.

Consider a scenario where we want to do a (1 second each) on records in a list with a billion items. Typically we may not need all the billion items processed (e.g. we may need only a filtered subset).

Let's define a little utility function to help us monitor memory usage and another function that takes 1 second to do its job.

In the functions above we use java.lang.Runtime and java.lang.Thread for getting free memory and supporting sleep.

We will also be using the built in function to measure our performance.

Here is a simple usage at REPL:

user=> (defn free-mem [] (.freeMemory (Runtime/getRuntime)))
 * 1) 'user/free-mem

user=> (defn big-computation [x] (Thread/sleep 1000) (* 10 x))
 * 1) 'user/big-computation

user=> (time (big-computation 1)) "Elapsed time: 1000.339953 msecs" 10

Now we define a list of 1 billion numbers called.

user=> (time (def nums (range 1000000000))) "Elapsed time: 0.166994 msecs"
 * 1) 'user/nums

Note that it takes Clojure only 0.17 ms to create a list of 1 billion numbers. This is because the list is not really created. The user just has a promise from Clojure that the appropriate number from this list will be returned when asked for.

Now, let's say, we want to apply  to x from 10000 to 10005 from this list.

This is the code for it:

Putting this code at the REPL, this is what we get:

user=> (free-mem) 2598000 user=> (time (def v (apply vector (map big-computation (take 5 (filter (fn [x] (and (> x 10000) (< x 10010))) nums)))))) "Elapsed time: 5036.234311 msecs" user=> (free-mem) 2728800
 * 1) 'user/v

The comments in the code block indicate the working of this code. It took us ~5 seconds to execute this. Here are some points to note:
 * It did not take us 10000 seconds to filter out item number 10000 to 10010 from the list
 * It did not take us 10 seconds to get first 5 items from the list of 10 filtered list
 * Overall, it took the computation only 5 seconds which is basically the computation time.
 * The amount of free memory is virtually the same even though we now have the promise of a billion records for processing. (It actually seems to have gone up a bit due to garbage collection)

Now if we access v it takes negligible time. user=> (time (seq v)) "Elapsed time: 0.042045 msecs" (100010 100020 100030 100040 100050) user=>

Another point to note is that a lazy sequence does not mean that the computation is done every time; once the computation is done, it gets cached.

Try the following: user=> (time (def comps (map big-computation nums))) "Elapsed time: 0.113564 msecs"
 * 1) 'user/comps

user=> (defn t5 [] (take 5 comps))
 * 1) 'user/t5

user=> (time (doall (t5))) "Elapsed time: 5010.49418 msecs" (0 10 20 30 40)

user=> (time (doall (t5))) "Elapsed time: 0.096104 msecs" (0 10 20 30 40)

user=>

In the first step we map  to a billion. Then we define a function  that takes 5 computations from comps. Observe that the first time t5 takes 5 seconds and after that it takes neglegible time. This is because once the calculation is done, the results are cached for later use. Since the result of  is also lazy,   is needed to force it to be eagerly evaluated before   returns to the REPL.

Lazy data structures can offer significant advantage assuming that the program is designed to leverage that. Designing a program for lazy sequences and infinite data structures is a paradigm shift from eagerly just doing the computation in languages like C and Java vs giving a promise of a computation.

This section is based on this mail in the Clojure group.

Infinite Data Source
As Clojure supports lazy evaluation of sequences, it is possible to have infinite data sources in Clojure. The infinite sequence (0 1 2 3 4 5 ....) can be defined using (range) since clojure 1.2:

Here we see two functions that are used for create an infinite list of numbers starting from 0. As Clojure supports lazy sequences, only the required items are generated and taken of the head of this list. In the above case, if you were to type out (range) or (iterate inc 0) directly at the prompt, the [http://clojure.org/reader reader] would continue getting the next number forever and you would need to terminate the process.

is a function that continuously applies f to the result of the previous application of f to x. Meaning, the result is. first gives 0 as the result, then, then   and so on.

basically removes  items from the collection. There are many variation of this theme:
 * (take n coll)
 * (take-nth n coll)
 * (take-last n coll)
 * (take-while pred coll)
 * (drop n coll)
 * (drop-while pred coll)

The reader is encouraged to look at the Clojure Sequence API for details.

List Comprehension
List Comprehensions are the constructs offered by a language that make it easy to create new lists from old ones. As simple as it sounds, it is a very powerful concept. Clojure has good support for List comprehensions.

Lets say we want a set of all  for all   with   starting from.

Here is one way to do it in Clojure:

is the infinite list of numbers that we saw in the previous section. We need to  for the set as we are creating an infinite source of numbers. Running it directly at the prompt will make the suck out numbers from this source indefinitely.

The key construct here is the  macro. Here the expression says that x comes out of  one at a time. The next clause  basically says that x should be pulled out only if it meets this criteria. Once this x is out, is applied to it. Binding all this to  gives us an infinite set. Hence, the  and the expected result that we see.

Another way to achieve the same result is to use  and .

Here we create a predicate  and pull out x's from nums only if this predicate is satisfied. This is done by . Note that since Clojure is lazy, what gives is only a promise of supplying the next number that satisfies the predicate. It does not (and cannot in this particular case) evaluate the entire list. Once we have this stream of x's, it is simply a matter of mapping inc to it.

The choice between List Comprehension i.e.  and is largely a matter of user preference. There is no major advantage of one over the other.

(first coll)
Gets the first element of a sequence. Returns nil for an empty sequence or nil.

(rest coll)
Gets everything except the first element of a sequence. Returns nil for an empty sequence or nil.

(map f colls*)
Applies f lazily to each item in the sequences, returning a lazy sequence of the return values of f.

Because the supplied function always returns true, these both return a sequence of true, repeated ten times.

These two functions both multiply their argument by 2, so (map ...) returns a sequence where every item in the original is doubled.

(map ...) may take as many sequences as you supply to it (though it requires at least one sequence), but the function argument must accept as many arguments as there are sequences.

Thus, these two functions give the sequences multiplied together:

But the first one will only take two sequences as arguments, whereas the second one will take as many as are supplied.

(map ...) will stop evaluating as soon as it reaches the end of any supplied sequence, so in all three of these cases, (map ...) stops evaluating at 5 items (the length of the shortest sequence,) despite the second and third giving it sequences that are longer than 5 items (in the third example, the longer sequence is of infinite length.)

Each of these takes a a sequence made up solely of the number 2 and a sequence of the numbers (0 1 2 3 4) and multiplies them together.

(every? pred coll)
Returns true if pred is true for every item in a sequence. False otherwise. pred, in this case, is a function taking a single argument and returning true or false.

As this function returns true always, (every? ...) evaluates to true. Note that these two functions say the same thing.

(pos? x) returns true when its argument is greater than zero. Since (range 10) gives a sequence of numbers from 0 to 9 and (range 1 10) gives a sequence of numbers from 1 to 10, (pos? x) returns false once for the first sequence and never for the second.

This function returns true when its argument is an even number. Since the range between 1 and 10 and the sequence (1 3 5 7 9) contain odd numbers, (every? ...) returns false.

As the sequence (2 4 6 8 10) contains only even numbers, (every? ...) returns true.

If I had a need, elsewhere, to check if a number were even, I might, instead, write the following, making (even? num) an actual function before passing it as an argument to (every? ...)

Complementary function: (not-every? pred coll)

Returns the complementary value to (every? pred coll). False if pred is true for all items in the sequence, true if otherwise.

Looping and Iterating
Three different ways to loop from 1 to 20, increment by 2, printing the loop index each time (from mailing list discussion):

Mutual Recursion
Mutual recursion is tricky but possible in Clojure. The form of (defn ...) allows the body of a function to refer to itself or previously existing names only. However, Clojure does allow dynamic redefinition of function bindings, in the following way:

Mutual recursion is not possible in internal functions defined with. To declare a set of private recursive functions, you can use the above technique with  instead of , which will generate private definitions.

However one can emulate mutual recursive functions with  and.

Macros
A nice walkthrough on how to write a macro can be found at http://blog.n01se.net/?p=33 by Chouser.

Macros are used to transform data structures at compile time. Let's develop a new  macro. The  special form of Clojure evaluates all containing forms for their side-effects and returns the return value of the last one. should act similar, but return the value of the first sub-form.

In the beginning one should first think about how the macro should be invoked.

The return value should be. Then the next step is to think about how we would do this manually.

This first evaluates :x, then :y and :z. Finally the let evaluates to the result of evaluating :x. This can be turned into a macro using  and.

So what happens here. It is just a simple translation. We use the  to create a temporary place for the result of our first form to stay. Since we cannot simply use some name (it might be used in the user code), we generate a new one with. The # is a special notation of Clojure to help us: it generates a new name, which is guaranteed to be not used by the user code. The  "unquotes" our first form, that is   is replaced by the first argument. Then the  is used to inject the remaining forms. Using the  basically removes one set of  from the following expression. Finally we refer again to the result of the first form with.

We can check the expansion of our macro with.

Libraries
The lib package from  is now integrated into clojure. It is easy to define libraries that can be loaded by other scripts. Suppose we have an awesome  function which we want to provide to other developers. So what do we need? First we settle on a namespace, eg. . Now we have to create a file in the classpath with the filename "example/ourlib.clj". The contents are pretty straight forward.

All we have to do now is to use the functionality of. Suppose we have another file, where we want to use our function. lets us specify our requirements in a lot of ways. The simplest is

But what if we need the  function several times? We have to type always the namespace in front. We could add a, but we can have this easier. Just use  instead of  ! loads the library as  does and immediately  s to the namespace.

So now we have already two small libraries which are maybe used in a third program.

Again we can save some typing here. Similar to  we can factor out the common prefix of our libraries' namespaces.

Of course  contains 738 more functions, not only those shown above. We don't really want to have  because bringing in so many names risks conflicts, but we also don't want to type the namespace all the time either. So the first thing we do is employ an. But wait! You guessed it:  helps us again.

The  takes care of the aliasing and now we can refer to our   function as  !

Up to now it is already quite nice. But if we think a bit about our source code organization, we might end up with the insight that 739 functions in one single file is maybe not the best idea to keep around. So we decide to do some refactoring. We create a file "example/ourlib/add1.clj" and put our functions there. We don't want the user to have to load many files instead of one, so we modify the "example/ourlib.clj" file to load any additional files as follows.

So the user still loads the "public" example.ourlib lib, which takes care of loading the rest. (The :load implementation includes code to provide the ".clj" suffix for the files being loaded)

For more information see the docstring of require -.