Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I love Clojure. Why? Partly because I am lazy. Larry Wall said a good programmer is lazy, but in my case I am lazy in the wrong ways. If you have enough self-discipline, then you probably don't need immutability. But immutability is a wonderful thing if you are lazy.

I also love immutability because I have had many co-workers who are lazy. Again, not aways the good kind of lazy. I mean the kind of lazy that allows 2 loops with mutable variables into the same function:

howMuchPrizeMoney = 0;

arrayOfMoneyPerCategory =[];

for (i=0; i < users.length; i++) {

    u = users[i];

   howMuchPrizeMoney += u.prize_money;    
}

for (i=0; i < contests.length; i++) {

  c = contests[i];

  for (j=0; j < categories.length; j++) {

        cat = categories[i];  

       if c.name == cat.name {

         arrayOfMoneyPerCategory[cat.name] =   u.prize_money;  

     }

  }
}

Wait, now I have a bug! All the categories have the same amount of money, and I know that is wrong. Where is that bug? Hmm, let me look and look and look. And if this example seems easy, I have seen functions larger than this, where finding the bug gets much harder. I am lazy, and my co-workers are lazy, and if we allow ourselves mutable variables, we will abuse them, so I would be happy if we adopted a language that avoided mutable variables. So for instance, even if I had a loop that looped over all the variables, there would still be no risk of one variable effecting another if I did something like this:

(def vector-of-users [

                        {:name :henry :prize-money 200}   

                       {:name :henry :prize-money 30}   

                       {:name :craig :prize-money 340}   

                       {:name :craig :prize-money 100}   

                       {:name :pasha :prize-money 2330}   

                       {:name :pasha :prize-money 1130}   

                       {:name :pasha :prize-money 430}   

                       {:name :eli :prize-money 60}   

                       {:name :eli :prize-money 330}   

                       {:name :eli :prize-money 89}   ])
(loop [u vector-of-users total 0]

     (if (first u)

       (recur 

           (rest u)

           (+ (:prize-money (first u)) total))

      total))

At the REPL, this gives me 5039.

Now if I do this, and I stupidly put next a loop inside of a loop, is there any risk of a typo? Sure, but I won't get a confusing number back, instead I'll be told that I'm using a var that doesn't exist.

This is the version without the typo:

(def vector-of-categories [:housing :crisis :restaurants :theater])

(def vector-of-contests [

                        {:category :housing :prize-money 200}   

                       {:category :housing :prize-money 30}   

                       {:category :housing :prize-money 340}   

                       {:category :crisis :prize-money 100}   

                       {:category :crisis :prize-money 2330}   

                       {:category :restaurants :prize-money 1130}

                       {:category :restaurants :prize-money 430}   

                       {:category :restaurants :prize-money 60}   

                       {:category :theater :prize-money 330}   

                       {:category :theater :prize-money 89}   ])
(loop

[money-per-category {}

contests vector-of-contests

categories vector-of-categories]

(if (first categories)

(recur

   (assoc money-per-category (first categories) 

       (loop [c contests total 0]  

         (if (first c) 

             (recur 

                (rest c) 

                (if (= (:category (first c)) (first categories)) 

                   (+ total (:prize-money (first c))) 

                    total))

           total)))

   contests

   (rest categories))
money-per-category))

When I try this at the REPL I get:

{:theater 419, :restaurants 1620, :crisis 2430, :housing 570}

But what if I made a typo, just like in the first example? What if instead of this:

(first c)

I stupidly wrote:

(first u)

There would be no "u" that was in scope for the whole of the function. The "u" would only exist inside the first (loop).

Needless to say, no one would ever write Clojure code like this. Anyone who puts 3 loops in function, in Clojure, is taken outside and shot at point blank range. But my first example, in Javascript, is something I have seen in real life.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: