Reaching Clojure on Java
Read Java: Evolutionary Dead End on Artima first, then come back here.
…Done?
Well, I couldn’t agree more. Java – the language – has got to stabilise. I’ve had an uneasy feeling about it ever since those God-awful generics were shoe-horned onto it and now I get the heebee-jeebees every time I hear of the new ‘features’ they intend to tack on in Java 7. Closures? Weird imports? Enough already!
Now I’m not saying that all these proposals are without value, but I get the distinct feeling that Java is suffering from a severe case of ‘language envy’. If C#’s got it, Java’s got to have it too. And like a middle-aged businessman passing through a mid-life crisis and dressing two decades younger than he should, Java wants to fit in with the cool crowd. Ruby’s got closures? We want them too! Groovy and Scala have built in support for XML? Hell, lets pile that on as well! The Java crowd has still to realise that the battle for cool was lost a long, long time ago. There’s no point getting all tooled up and charging the enemy now.
Java has found its niche. It’s an excellent language for large, complex enterprise applications. It’s perfect for building massive, scalable apps using large teams of programmers. It’s got excellent tool and library support and it does what it does quite well. It’s COBOL for the 21st century and there’s Nothing Wrong With That!
The JVM
However, we need to make a clear distinction between Java (the Language), Java (the JVM) and the Java Class Libraries. The Java language needs to stabilise and the Class Libraries need to be cleaned up and slimmed down a bit, but the JVM is absolute gold. It’s the best part of the entire stack and an excellent target platform.
The Java language is IMHO, the weakest part of the chain. It’s good for enterprisy apps built by large teams of trained monkeys skilled programmers, but not so great if you have more kinetic needs. All the language features which help enforce some modicum of control are precisely what come in your way when you need to rapidly prototype a solution. However, you don’t need to throw the JVM baby out with the Java bathwater. You can still leverage the JVM by using the plethora of languages which build upon it, like JRuby, Jython, Groovy, Scala and no doubt a whole stable-full of more esoteric options. You can use a language more suitable to the task at hand without having to abandon the vast ecosystem of high quality Java libraries and that sweet, sweet virtual machine.
Clojure, on Java
So let’s segue smoothly to the real topic I wanted to discuss.
Clojure.
Groovy is nice and Scala is sweet, but I’ve had an unfulfilled hankering for a good Lisp on the JVM for a very long time. There are some Common Lisp implementations which work on the JVM, but there’s a difference between a language which has been ported to run on the JVM (E.g. JRuby, Jython) and one which has been designed to run on the JVM (E.g. Groovy). There’s an unpleasant impedance mismatch when you try to stick one language environment on top of another. For example, while using Jython, should I use the Python libraries or the Java ones? Can I easily pass the return values generated by one set of libraries to the other? Mixing them both together is ugly and error prone.
That’s one reason a language like Groovy feels so much better. Since it’s targeted at the JVM, it follows a well-know set of idioms and patterns. It’s easy to pick up and comfortable to use.
So I was on the lookout for a Lisp which didn’t just run on the JVM, but embraced it. And eventually, I found Clojure. It’s precisely what it says on the label and presses all my buttons. It’s a Lisp for functional programming with excellent support for concurrency, targeting the JVM. In fact, the STM support is based on MVCC, which is the first time I’ve heard of someone using this technique for thread transactions. It also has excellent support for calling Java code from within itself (the ‘.’ is beautiful)
A good Lisp on the JVM has the potential to be a real blockbuster. I detest the closed feel of most CL implementations and Clojure feels like a breath of fresh air. The ability to fit in with a multi-lingual and multi-paradigm world is IMHO essential for any general purpose language.
Requests and unsolicited advice
Since I’m feeling both excited and generous (ha!), here’s some unsolicited advice for Rich Hickey, the guy behind it all.
- Read Yegge’s Lisp is not an acceptable Lisp: No doubt he already has, but as a newcomer to lisp, I can agree with a lot of what he says, especially about the moribund community and general lack of direction and vision.
- Don’t emphasis the Lispness of Clojure: Yes it’s a Lisp and there’s no way to hide that, (not (with (all (those parentheses)))), but talk about all the cool things you can do with Clojure, not why it’s a better Lisp. You need to reach out to the people looking for a cool language, not try and convert existing lisp fanatics. For the great unwashed, the Lisp heritage is a negative and that has to be accepted and death with. BTW, it looks like the Logix guys agree, ‘cause what they’ve come up with looks like an infix Lisp without the parentheses to me! No mention of Lisp on their front page, though you’ll find plenty in the docs.
- Better Documentation: This is related to points 1 and 2. The docs are decent, but only if you already have a fairly good idea about Lisp. They need to start from a far more basic level (take a look at Arc's Tutorial for example). No one needs to write a book on Clojure (yet), but you do need lots and lots of code samples, starting from “Hello World” to a complete application, exercising different parts of the language. A wiki would be nice too.
- IDE Support: It’s an obvious hole. Target Eclipse or NetBeans, not Emacs. Remember, if you really want to reach critical mass, your target audience is going to be Java weenies and not Lispers!
- RAD tools: You need Clojure on Rails, or something. I personally think magical frameworks like Rails aren’t a very good idea, but apparently there are lots of people out there who disagree.
- Better OOP support: Remember, you’re trying to interop with Java. Being able to extend and define classes and interfaces in Clojure itself would be nice.
- Spread the word!: I literally stumbled across Clojure while reading a thread on Reddit. You need to start screaming about the language from the roof-tops! :-) Get the word out. Ruby is going through a bad patch now and there’s plenty of bloggers out there looking for The Next Big Thing. Get them to start talking about Clojure and you’ve got it made. But you need to have better docs and IDE support in place first.
If all this has piqued your interest, check out the docs on the Clojure site, and listen to the Clojure presentation (audio / pdf). They’re worth the time.
So that’s how I reached Clojure on Java (what a terrible pun! I’m almost ashamed. Almost.). Am I going to adopt it as my alternative language? It’s too early to tell. But I am going to be keeping a very close eye on it.
Note: Arc's out. And by that I mean it's out of the running. No Unicode support and it's just another gated Lisp dialect. Sorry Paul, no cookie for you.
Socialize: del.icio.us | digg | reddit | Technorati | Yahoo My Web
9 comments:
Aren't these two statements contradictory:
* Clojure is better than Jython or Jruby because it feels more integrated into the JVM
* Being able to extend and define classes and interfaces in Clojure itself would be nice.
The JVM is all about classes and interfaces!
Closure is a functional programming language. Immutable state and all that. And it is interoperable with java code. This makes it possible to write java (java language) code that mutates state (mustates ?), and use this code from clojure. This in turn allows for the idiom of functional programming to be broken easily by people who don't care about it.
I don't see the point of imposing functional style on a language, and allowing it to do object interop with libraries whose authors did not have functional programming languages in mind when they wrote their code.
What have I missed?
- Joel.
For anon no.1
It's Java which is all about classes and interfaces, not the JVM. That's all about java byte code. As long as your language compiles down to correct byte code, you're good to go.
@Joel
I get what you're saying.
2 points
1. No one's forcing you to use Java code. You can attain functional purity by simply re-writing the class libraries yourself, but in Clojure this time.
2. Rich made a good point in his presentation about pure functional programming, basically saying there's no such thing. A purely functional program can have zero side-effects, which means all it can do is warm your computer up. And an audience member pointed out that even that's a side effect, so it can't even be allowed to do that! :-) Clojure just makes functional coding easier because of the rich set of immutable datatypes. But if you actually want to get anything done, you need to be pragmatic.
I'm now using Scala instead of Java. I can't see any incremental value in using Clojure... maybe the STM... but I have the Actor library in Scala. Until I get an IDE and/or something like Lift, why would I move?
Without further ado, a Clojure tutorial for non-Lisp programmers
A bit late to respond but still, Scala dosn't support immutability as well as Closure and its not dynamically typed, another short hand is that it requires a compilation stage that Closjure does not.
@Arsalan: JVM is not "all about bytecodes". Get your facts straight.
Bytecodes are loaded. By what? By *Class* loaders. No byte code, not even a single itty bitty is meaningful outside of an enclosing class, as far as JVM is concerned. That's why clojure (under the hood) defines and instantiates an extension of AFN (java class) for each function call in clojure.
* the Lisp heritage is a negative and that has to be accepted and death with.
Freudian slip?
*Better OOP support: Remember, you’re trying to interop with Java.
Hickey says in one of his videos at clojure.blip.tv that OOP is the spaghetti code of the new millenium, or words to that effect.
*Yes it’s a Lisp and there’s no way to hide that, (not (with (all (those parentheses)))),
He's also got an example with a small GUI (the Celsius converter, IIRC) that uses fewer parens than the equivalent Java code! He can do this because Clojure macros can rewrite code into other code.
Post a Comment