Hacker News new | past | comments | ask | show | jobs | submit login

I think I am qualified to answer this: I wrote reasonably complex systems in Common Lisp before I gradually moved to Clojure several years ago. I have written several fairly large apps and systems in Clojure and Clojurescript (this includes https://partsbox.io/ as my current project and apps like an e-commerce search engine processing hundreds of requests per second for many years).

I used to think Common Lisp was a fantastic language, but I always tried to keep an open mind remembering the Blub paradox. Then I started working with Clojure and after the initial friction (some things were just plain annoying in the beginning) things clicked for me. It was, quite simply, a much better language.

The major improvements over Common Lisp for me were: 1) immutable data structures: these days I can't even imagine dealing with code that mutates data in-place, 2) a great approach to concurrency and parallelism (it's really difficult to get yourself deadlocked in Clojure), 3) Rich Hickey coming out every year or so with a solution to yet another problem (core.async, transducers, spec), 4) really flexible data structures.

I know there are many CL advocates who will try to point out that CL has all these things. But these will be the same people who will be annoyed when Java programmers point out that Java has all these things, too. It's just a matter of friction, elegance and ease of use.

One additional factor which is often glossed over is Clojurescript. Most software these days exists in some form in the browser, too. Being able to use pretty much the same language (cljc files can be compiled both server-side and client-side to Javascript!) on both sides brings many advantages.

People sometimes ask me if I miss CLOS or the MOP. Not at all. It's a great set of concepts, worth learning (the green book makes for great reading). But I found that larger systems using CLOS were really difficult to understand and follow (just following the code flow is a nightmare if you have a lot of multimethods), and systems that used the MOP in any but the most basic ways were intractable without a debugger. Besides, please see above what I wrote about immutability: I'd much rather have immutable data structures.

Clojure's emphasis on functions and data, while it may be based in the 60s, is one of the really good ideas. And Clojure is really, really good at tackling complexity, it's just not apparent in the language design. While other languages focus on syntax sugar, Clojure's focus is on getting things done on a large scale. You don't see that, but things like namespaced keywords, clojure.spec, pre/post conditions, maps, sets, all play together to allow you to create extensible and reusable code.

Also, it's easy to discount certain solutions in Clojure as "also existing" elsewhere, but without actually using them in real systems one often doesn't see the full advantage. Transducers are a good example: I think they are under-appreciated and under-utilized. Common Lisp veterans will laugh and say that SERIES did the same thing back in the 80s. But SERIES was all about optimization and anyone who actually tried to use it will have stories to tell about how easy it is to use. Transducers, on the other hand, if used to build data-processing pipelines processing Clojure maps with namespaced keys, are an elegant and efficient tool for building composable systems. Plus, once you've coded your pipeline using transducers, it's a snap to parallelize it.

Looking at it differently: to "get" Clojure one has to understand that there is no silver bullet: no single revolutionary "feature". Instead, the gains come from tiny improvements all over the place: immutable data structures, good built-in library for dealing with them, core.async, transducers, spec, Clojurescript, not having to convert to JSON or XML on the way to the client, re-using the same code on server-side and client-side, and more.

In practical terms, I would never be able to write and maintain by myself the system I'm currently working on (https://partsbox.io/) without Clojure and Clojurescript. It isn't impossible, but I can't imagine tackling the complexity in a comparable time frame.

I can't imagine going back to Common Lisp. I sometimes have to look at the code I've written in CL, and it looks clunky. Especially place-oriented programming (setf all over the place) is something I really really don't want to go back to. It's a nightmare, particularly if you intend to have any kind of concurrency.

I still try to keep an open mind, remembering about the Blub paradox. I make it a rule to regularly check and learn about new languages. There are some which I found really good for certain types of applications and which I would use instead of Clojure in certain cases (Elixir is a good example). I still haven't found anything comparable which is a general-purpose language, especially if you consider the client-side story — but I'm checking all the time

See also my answer to a similar question posted on Quora several years ago: https://www.quora.com/What-do-veteran-Lisp-programmers-think...

Also, as a general observation: most (not all, but most) criticism of Clojure seems to be written by people who did not write anything significant in it, and much of that by people who simply do not write large software systems at all. Reading many discussions, I gloss over most comments, as they are simply beside the point and not even worth addressing.

This is really interesting, I write mostly Common Lisp as hobby projects (at varying levels of scale, I've submitted patches for sbcl and mcclim and I've written a bunch of libraries) and at work I help maintain a data pipeline written in Clojure. I've generally found that I much prefer the "feeling" of writing Common Lisp and have come to think that immutability in the core + being hosted on the jvm forces some compromises on the interactive development front that make writing Clojure always feel like something of a chore.

I had similar feelings in the very beginning, but I was quickly won over (I didn't see compromises in interactive development, though, unless you mean difficult debugging because of lazy sequences). Debugging in general was something I missed the most (after all, even in CL, I implemented return-from-frame in CMUCL to get better interactive debugging). And to this day I think CL has better interactive debugging than Clojure.

But Clojure has so many advantages that it isn't even a close contest.

Also, most of the code I write today isn't hosted on the JVM, it runs in the browser. Or gets compiled to both JVM bytecode and highly optimized JavaScript.

The more I've used Clojure, the less I've liked it: protocols don't work correctly, multimethods are badly designed, core.async isn't source-compatible between CLJ/CLJS, unless you know what to avoid, etc.

As far as interactive development compromises go, I'm mostly thinking about how in Clojure, it seems like the only practical way to load your new code is to use something like tools.namespace/refresh (or whatever it is). And, that essentially involves throwing away everything and rebuilding it from scratch: while that has some nice properties (e.g. you don't end up with an inconsistent image state), it's also really annoying because you have to restart all your servers, etc.

And, the other thing that makes CL standout from every system I've used except Smalltalks, is that Quicklisp loads third party systems into the current image without restarting: there are a bunch of tools I've seen floating around that claim to be able to do this for Clojure, but I've never really been able to make any of them work consistently.

Much of what you describe reminds me of when I started playing with Kotlin and the fresh feeling it gave me that made me not want to use other languages again. Simplicity and just getting stuff done. I see Rich Hickey had kind words for Kotlin on his last conference talk.

That's really cool to see that you built a BOM system in Clojure. I worked with BOM data for electronics a lot in my last job and while I was mostly confined to using SQL to do it (recursive CTEs ugh), I often thought about how much easier it would be to manipulate the BOM hierarchy structure in a lisp-like language.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact