Wednesday, 13 August 2014

Clojure, syntax and readability

def isValidVoter(p:Person) = p.age > 18 && !p.isInPrison

vs

(defn is-valid-voter [p] (and (> (:age p) 18) (not (:in-prison p))))

The first expression is in Scala, the second in Clojure. As much as I appreciate the simpleness of Clojure-syntax, I can't help but find the Scala version much easier to read. The Clojure version can be enhanced by line breaks

(defn is-valid-voter [p]
  (and 
    (> (:age p) 18) 
    (not (:in-prison p))))

but now it's a four-liner instead of a one-liner. And yet still less readable than its Scala counterpart. Furthermore, if I want to remove the "in-prison" part, in Scala I just remove the end of the expression from the && sign without touching anything from the left of it.

def isValidVoter(p:Person) = p.age > 18 && !p.isInPrison

In Clojure I have to remove the 'and' clause, thus changing the number of parantheseses before and after  (> (:age p) 18). This is not directly related to readability, but also the result of Lisp-syntax.

Back to the question of readability, part of it is due to our learnt preference for infix notation. But the real reason is, I think, is that the different parts of the function definition, such as name, arguments, body, just don't stand out in Lisp. Check this

(defn wrap [x] [x])

This little function does nothing but wrap the input in a vector. The argument list and the body are 100% identical. Even after some exposure to Clojure it can look puzzling for a second. In Scala the two sides of the '=' sign are obviously stand apart. Syntax highlighting, but the syntax itself makes it easy capture the whole in one glance, exactly because the syntax is rigid and there are rules it has to abide. Lisp on the other hand has a syntax so simple we can almost say has no syntax at all. Everything is a list (S-expression to be exact), the first element is the function name, the rest are its arguments (let's forget about special forms and macros for now). That's it.
It lacks arbitrary rules like "there is a '=' between the expression signature and the body", "prefix a boolean expression with an '!' negates it" or "get the field of an object with <object>.<field>", and so on. Taking uniformity to its extreme, undeniably some readability is lost.  But what is gained is not only the esthetic statisfaction over the ultimate simplicity, but the power coming from homoiconity, macros. Macros are discussed elsewhere, but I'm as much as fascinated by the simplicity itself as by the power it brings. There are many syntaxes with different advantages and disadvantages. Languages are evolving and we can't know how a programming language will look like in a hundred years. But Lisp is on a very end of the spectrum. It cannot get any simpler.

No comments :

Post a Comment