views:

2127

answers:

3

How practical is it to port a Common Lisp application to Clojure? To be more specific, what features exist in Common Lisp that do not exist in Clojure, and would have to be re-written?

+5  A: 

I don't have a specific answer, but I'd recommend these resources:

  • Rich Hickey's two part talk Clojure for Lisp Programmers
  • Stuart Halloway's work on translating the examples from Peter Seibel's Practical Common Lisp to Clojure.
zweiterlinde
I don't believe that work is by Peter Seibel. Stuart Halloway is the one porting from CL to Clojure.
Brian Carper
Thanks, Brian. Fixed. I did just buy Stuart's preprint, so perhaps he'll forgive me :)
zweiterlinde
+7  A: 

There are a number of accounts of transitioning from CL to Clojure (blog , another blog, Thread on HN).

The biggest problem a lot of CL'ers have with Clojure when they first check it out is it's lack of Tail Call Optimization, which isn't possible on the the JVM.

Brian Gianforcaro
That's why you use recur instead.
Benjamin Confino
and trampolines as well. However there has been some progress on getting TCO into the JVM via the OpenJDK project.
dnolen
Many CLs don't, either (it's not required), and I don't know any program(mers) who depend on it. e.g., SBCL/CMUCL doesn't unless you use the dynamic-space optimization.
Ken
Its not impossible to have TCO in JVM. see this discussion. http://stackoverflow.com/questions/1168059/which-function-is-the-best-in-terms-of-stack-usage-efficiency-and-time
kunjaan
It's true that many CLs don't do tail call optimization either, but this is less of an issue in Common Lisp because it has a more imperative nature than Clojure.
Niten
+12  A: 

There's a list on clojure.org of differences between Clojure and other Lisps. Some other things I've noticed using Clojure:

  • Idiomatic Clojure leans heavily toward immutable data structures. Anywhere you see SETF in CL may have to be changed in Clojure to take full advantage. (You always have the option of using mutable Java data structures in Clojure, but most people don't.)

  • Clojure's multimethods are similar to CL's (arguably more powerful, because you can dispatch on things other than type) but a full-blown CLOS is not available in Clojure. Clojure uses struct instead, which is just a fancy hashmap. Java's OOP system is also available, of course. Some people are working on porting CLOS to Clojure but I'm not sure how far along those efforts are at this point.

  • Clojure macros work slightly differently than CL macros when it comes to symbol/namespace resolution. I'm not sure if I understand well enough to elucidate the differences. You don't have to mess with gensyms quite as much in Clojure though, which is nice.

  • Clojure doesn't have a condition system like CL's. You have only Java's try/catch/finally for exception handling.

  • Clojure doesn't allow user-defined reader macros.

  • Clojure doesn't have multiple return values. Destructuring in Clojure is very nice (supports lists, vectors, hash-maps, sets etc.) and it's built into more places than CL by default, so this is less of an issue than it could be.

Depending on the app and how it's written, it may be practical and straightforward to port from CL to Clojure, or it may be more practical to rewrite it from the ground up in a more functional, thread-safe way to fit better with Clojure style.

Brian Carper
Also Clojure is a Lisp 1 (with namespaces), whereas CL is a Lisp 2. This is a very important difference which effects macros hugely, and, to a lesser degree, variable and function declarations.
dsm
Clojure macros are closer to CL's than Scheme's. Clojure macros aren't hygienic but they make it much easier to be hygienic by default.
Brian Carper
CLOS multimethods can dispatch on type or identity. What else can Clojure dispatch on?
Anonymous Coward
It can dispatch on anything. You supply your own arbitrary dispatch function.
Brian Carper
There is a user contrib library called error kit which implements much of CLOS condition/restart handling.
David Plumpton