Wednesday, September 7

Things that freak me out about Clojure

Coming from a Common Lisp/C++ background to Clojure is kind of .. interesting... there are several things that have made me take pause and wonder if Common Lisp is doing things the right way.

* Maps and Sets are functions. You can apply a value to a set and it returns that value if it's a member, nil if it's not. Similarly with maps. Apply a value to a map and it either returns nil, or the value the value maps to in the map. Seems strange at first but it allows some neat filtering tricks

* Keywords are functions. Keywords evaluate to themselves, just like in CL. Unlike in CL they are also functions so (:keyword map) actually tests map for membership of :keyword and returns the value mapped to the keyword. Again, this is handy.

* -> : This macro flattens out nested function calls so (-> fn1 fn2 fn3) is (fn1 (fn2 (fn3))). I really dislike this: I can see how coming from Java it would seemingly make code easier to read, and reduce syntatic noise, but I find the parens useful as a guide for indentation. This might be down to taste.

* Iteration is totally different. There's nothing like the LOOP or ITERATE. There is a while and a loop/recur, but the sequence handling is sufficently powerful that this is a fallback. It forces me to think differently and this is definitely a good thing.

* Probably more to come, but meanwhile I'll keep in mind these rules for writing Clojure.

1 comment:

J.V. Toups said...

Much of the difference in iteration constructs has to do with the fact that clojure emphasizes laziness, particularly over sequences. There is a `for` construct, for instance, but it produces a lazy sequence. Laziness is is much more important in functional languages because you're map/filtering a lot and each operation constitutes a complete sweep through the sequence, unless the sequences are lazy, in which circumstance the lazy map and filter semantics kind of fuse multiple maps and filters and so on together.

I actually don't know quite how to feel about laziness in clojure. I think its somewhat difficult to get a sense for which operations preserve and which operations destroy laziness, because it is all implicit.