Java vs Clojure - Lets talk ceremony!
2009-09-07 07:29:34

So, maintaining the perspective of a businessman, lets talk ceremony.
There are undoubtedly multiple definitions of 'ceremony in code', but i'll boil it down to this
All use of resources for the sole purpose of pleasing an unforgiving and inflexible compiler and/or ritual
For IT Directors, looking at resource waste in the code itself is a discipline scarcely applied but for the rest of us its worth giving some attention. If I have my car in the shop for a tune-up I want the mechanic to use the right tools and thereby bill me the least amount of man-hours. Similarly if I'm going to pay somebody to write code for me, I want them to be as efficient as possible, which generally means
- Minimize the amount of time spent on bugfixing
- Maintain simplicity through the code
- Use the right tools for the job
And by using the right tools I mean those where you get the most functionality for the least amount of code and to achieve that, I have need to do away with ceremony.
Learning by example!
Differences become apparent in comparisons, so lets stack
Java ( a typical OO, statically typed, curly braces language ) against
Clojure ( a functional Lisp-1 geared for concurrency ).
The task: I want to define a list of an arbitary amount of elements. Parse this list and only return those element which are distinctive, ie. remove duplicates. First I'll show you some Java code which gets the job done, talk about it, then compare.
[caption id="attachment_29" align="aligncenter" width="430" caption="code-snippit"]

[/caption]
People reading this code who are not carrying with them a great deal of sympathy for ceremonial waste of their money will probably have the following questions:
Q: Why do I need all the imports?
A: Java has lots of dependencies which are all present in the standard Java installation. This is a clever way to structure the code.
Q: Okay, but why do I need to write 'import' on every line... That seems redundant!
A: Thats ceremony.
Q: Why do I need a class for this?
A: Because classes are the only place you can puts methods, and methods is the only place you can put code.
Q: Why do I need to specifically tell Java that my elements are of type <String>?
A: Because Java is statically typed, so its not willing to work out the obvious, a string is a string. Basically you're paying me to do the compilers job.
When you run this Java program, dlist will contain "foo" "bar" "baz" when exiting. Thats the result we were going for. Lets try to write a Clojure program which does the very same thing. For newcomers: Dont be distracted by the "user>" prefix on every line, thats how Clojures REPL tell me which namespace I'm in. Since Clojure development is very interactive I just write my code, hit enter and it compiles and runs.
[caption id="attachment_29" align="aligncenter" width="350" caption="code-snippit"]

[/caption]
So, we went from 28 lines down to 1. And before I get into the details ask yourself this question:
When bug-hunting, which version is easier to reason about?
In Clojure I can have classes, but I dont have to. I can define object of any type, but only when I need to. I can of course have code, but I dont need to stick it in methods. Since Clojure is a functional language, I have all my sequence techniques (like distinct) right in the core.
Now the critics might say:
"This is a set up. You picked an example for which you knew Clojure had a function" and thats right, I did. But not wanting to win by means of cheating, I've also written a Clojure version which mimics the Java version:
[caption id="attachment_31" align="aligncenter" width="438" caption="code-snippit"]

[/caption]
Down from 28 to 9 lines. I still have my imports (though I didnt need them), but Clojure doesnt want me to write neither 'import' nor 'java.util.' more than once. I define my list 'lst' using 'let' and I can stick as many items in there,
and of any type, that I want. If I wanted to add a element with the value "quux" this is the code I needed to write:
Java: list.add("quux");
Clojure: "quux";
If I wanted to add the an integer of the value 5 I would need to restructure my entire Java program, in Clojure I'd write: 5. But like you might have guessed from the 'distinct' example, loops are often not the best way to go and a more idiomatic example would be:
[caption id="attachment_44" align="aligncenter" width="396" caption="code-snippit"]

[/caption]
Some might "Sure thats actually only 4 lines of code, but they're difficult to write!" and thats exactly right. But isn't that what you want to be paying your hard earned money for? Competent code writers who have the skills to write quality code? As a buyer of a service my concern is not on the amount of training the consultant had to go through, but that the quality that I get out - I want my dollars worth!
Can a shorter version of the java code be produced? Yes it can, I think by altering the imports to * (which has a different effect) and using list comprehension instead of an iterator you can trim some 10 lines of it. But thats beside the point. If you want you can do functional programming in QBasic, but at the end of the day its the things which your tools default to, that will dominate your approach.
Conclusions:
I appreciate being comfortable in a language as much as anybody, but once we start mixing development with money we need to make good decisions. I've witnessed a lot of language wars which quickly turn into emotional rants. Nobody benefits from this. Examine your own tools. How much money, time and resources are you giving to ceremony? How much are you and your clients paying for the comfort of '
what we always did' ?
/Lau