Monday, April 26, 2010

let and binding macros in Clojure

Clojure has a special form called "let" and "binding", which are actually implemented as macros. It can get confusing sometimes.  If you have read "Programming Clojure" book, you might be thinking that it is easy to use them correctly considering following straightforward example:
Basically, "let" creates a lexical scoped Vars, which is local to the code block or a procedure where it is initially defined. Therefore, in the example above, "let" just created a new "x" with the value of "new value". But it is not local to the function "print-x".  That is to say, "print-x" have no knowledge of the local scoped binding that is created by "let". "binding" macro instead creates a new binding for the already existed var, "x" with the "new value". Since "print-x" is evaluated within the "binding" form, the newly bound value is visible to any chained calls within the form.  All nice and easy. However, it is not that obvious to understand and use them correctly. Look at following example:
"let" example is just fine. It created a new var "y" with the value of 5 bound to it.  But what is going on with the "binding" example? If we dig little deeper to Clojure API doc, we learn that the new bindings in "binding" are made in parallel, not sequential as it is in "let". Therefore, existing var "y" gets bound to the root binding of "x" not the overshadowed value of "x", which is the case in the "let example".
OK, so far so good. Let us look at another example:
Line 20-29 is pretty straight forward. But how about line 30? Shouldn't  it call "print-y" function? Not really. It is because the anonymous function is evaluated outside of the "binding" form.





To see this in action let us try following:



The "#<user$eval__28$fn__30 user$eval__28$fn__30@bdb503>" is an indication that anonymous function did not get evaluated within the "binding" form.  Ok, now, how do you make sure it evaluates within the "binding" form? Here is what you do:



Just enclose the anonymous function within parenthesis.  What do we learn from all of the above? Here are the summary that helps one use "let" and "binding" correctly:
  • Use "binding" only if you are trying to alter a behavior dynamically for special-vars that is already defined. Enclose your special vars within * as recommended by idiomatic clojure to make your intent clear.
  • Use "let" for locally scoped vars and avoid shadowing already defined vars.
  • Remember "let" binding is sequential and "binding" binding is done in parallel.
  • Pay close attention to the scope of the "binding" form. Any expression that is not evaluated inside the form, will not see the binding. That is to say, binding in "binding" form is thread local starting from the "binding" form until it ends including any expression that is chained within the form, which is what the thread-local are all about.
I posted this so that it helps someone trying to find his or her way in the wonderful world of Clojure.  

Thursday, April 22, 2010

Easy way to start with Clojure developement

For any software developer, I recommend learning functional programming, which is especially true for anyone who spent quite a bit of time on doing Object Oriented Programming.  As far as my experience from Ruby -> Groovy -> Scala -> Clojure journey concerned, I strongly recommend learning Clojure to get into functional way of thinking in practical way.  One of the hurdles that I encountered in getting started with Clojure is lack of a simple way of setting the environment. Yes, there are many ways one can get started such as Lein, Maven+Clojure Plugin, Emacs+Swank+Slime, Vim+VimClojure, Eclipse+CounterClockWise, NetBeans+Enclojure, IDEA+LaClojure, you name it. But it all makes a newbie to spend days if not hours to get his or her environment right.  After playing the hard way( Emac+Swank+Slime, Vim+VimClojure), which I do not recommend for a new comer,  I ended up creating a project called ClojureW.  It is the easiest way to start with Clojure as far as I know for all three major OSes such as Windows, OS X and Linux.  Here is all you need to get going:
1.       Download Clojurew from: http://bitbucket.org/kasim/clojurew/get/tip.zip
2.       Unzip it to a folder and change to bin directory of this folder
3.       Just run clj to get a REPL or run clj cljscript.clj to execute your script.

For beginners, I recommend just using a text editor that highlights matching parenthesis.  Believe me, trying to set up an “IDE” for Clojure is painful if not disappointing at best.  The main thing that you learn from Clojure is to think bottom-up when solving problems.  You can practice this approach with any language but Clojure will force you to think this way.  Again, setting up IDE is a hindrance to what Clojure is really about at the beginning. You can play with IDEs once you get into idiomatic Clojure way of thinking.  As stated by a book titled, “97 Things Every Programmer Should Know”, being able to quickly type up a simple “Hello World” program and run it via command line can prove extremely valuable after all.#  

Sociable