The Blackstag BlogLogin
 Feeds RSS About  Categories: Everything  Hardware  Software  Programming  Finance  
Clojure Guide Chapter #6: Global Bindings & Anonymous Functions
Posted Jun 27, 2011 [category: Programming tag: Clojure]  Parent-Post  Leave-Comment  View-Comments  
Both data and functions can be bound to variable names (vars), using 'def'. For example, if we wanted to bind a string containing the alphabet characters to the variable name 'alphabet', we would do the following:
 =>(def alphabet "abcdefghijklmnopqrstuvwxyz")
OK, so what's the point? For starters, doing this means we no longer have to type the entire alphabet out for our code to make use of it:

In addition to being more convenient to use, vars ensure code is more meaningful when read. Say for example, you want to know how many characters there are in the alphabet:

=>(count alphabet)

With bound vars, as your code base grows you will discover that not only does your code become more succinct and therefore easier to read/maintain, but also your code becomes more efficient. More efficient? Yes, by making use of a value that's already been evaluated, your operations no longer need to perform that evaluation in each time or place you want to use it. To clarify that last point let's look at an example using a complex expression as an argument to the bind rather than data:

=>(def alphabet-length (count alphabet)) =>alphabet-length 26

Back to more efficient, right? Well, had your code needed to use alphabet-length many times, binding it once and re-using that value would certainly be more efficient than having to perform that count operation every time:

=>(+ alphabet-length alphabet-length) 52

This is due to the fact that it's really the result of evaluating (count alphabet) that was bound to 'alphabet-length' not the function itself. We can prove this by re-defining the original alphabet variable, such that calling the our function (count alphabet) will yield a new result. And yet still our alphabet-length variable will continue to hold the value 26, therefore we know the count operation is not run every time alphabet-length is evaluated.

=>(def alphabet "abc") #'user/alphabet =>(count alphabet) 3 =>alphabet-length 26
Binding Anonymous Functions

Of course that can lead to some problems should you actually want alphabet-length to account for changes in the alphabet right? Well, if we really want to we can in fact bind a function to a variable name such that the operation will be evaluated each time it's called. One way to accomplish this would be to pass in an anonymous function, using 'fn'. Take our alphabet-length variable, as an example, only let's pass in an anonymous function as the argument to def, this way when it's evaluated it will run the count operation each time it's called:

[1]=>(fn[](count alphabet)) user$eval6036$fn__6037 user$eval6036$fn__6037@6e3ebbb0 [2]=>(def alphabet-length (fn[](count alphabet))) #'user/alphabet-length

Notice in the above expression [1] our anonymous function, when evaluated, returns what appears to be an utterly meaningless string of junk. This just so happens to be Clojure's internal representation for a function which is not normally exposed to us. In expression [2] we have used 'def' to bind 'alphabet-length' to the function.

[3]=>alphabet-length user$alphabet_length user$alphabet_length@71d408f7 [4]=>(alphabet-length) 3

As you can see, evaluating expression [3], 'alphabet-length' also returns Clojure's internal representation for our function. Consequently we need to treat 'alphabet-length' like a function [4] and surround it with brackets such that Clojure knows to evaluate it as a function call. Now, following through on our example, we can re-define 'alphabet' back to its original value then call (alphabet-length) again, only this time we will see that it actually performs the count:

=>(def alphabet "abcdefghijklmnopqrstuvwxyz") #'user/alphabet =>(alphabet-length) 26
The Special Form for an Anonymous Function

It's worth noting that Clojure also provides a special form for anonymous functions that can make our expressions a little more succinct. To do this we will need to precede our function call with a hash symbol:

=>#(count alphabet) #<user$eval6182$fn__6183 user$eval6182$fn__6183@6de17d0b> =>(def alphabet-length #(count alphabet)) #'user/alphabet-length =>(alphabet-length) 26

In the event an argument needs to be passed into the function, we can then use the percent symbol to access the arguments value:

=>(def alphabet-length-plus #(+ (count alphabet) %)) #'user/alphabet-length-plus =>(alphabet-length-plus 2) 28 =>(alphabet-length-plus 3) 29

Additionally, we can also manage multiple arguments by attaching the numeric position of the argument to the percent symbol used within our operation:

=>(def alphabet-length-plus #(+ (count alphabet) %1 %2)) #'user/alphabet-length-plus =>(alphabet-length-plus 2 3) 31
Like This Post!
Chapter Links
 Comment posted on Jan 04, 2013 8:20 AM by  Trang Pham
Just to make it clearer for others:

In the count alphabet without and then with anon function binding:

 Without: (def count-alphabet (count alphabet))
Here (count alphabet) returns an integer thus the whole lines defines count-alphabet as an integer

With anon function binding: (def count-alphabet (fn[] (count alphabet))
Here we are defining count-alphabet as a function which returns the value of (count alphabet)

Hopefully this helps others understand why in one case redefining alphabet changes count-alphabet and the other it doesn't.
Would you like to leave a comment ?
Name (required):
Website (optional, creates link to name):
email address (private & optional, used for Gravatar):
Comment (required):
 (or Practice Markup Here)
Created by Blackstag Software Inc.Copyright Tim Robinson