Ex-Common-Lisper here. I spent many years writing software in CL, then discovered Clojure, and have been writing and maintaining a large production system in Clojure/ClojureScript for 10 years now.
I would not want to write anything in CL today.
CLOS is beautiful, but what it really boils down to in practice are multimethods. Which exist in Clojure. And which I barely ever use, because my software is easier to understand and debug without multimethods. Also, CLOS assumes mutability, which is not something I want anymore.
Clojure has a fantastic concurrency story, runs on the JVM, so you get an actively developed platform with thousands of man-hours of invested work. You get great GC, and all the Java libraries.
Then there is ClojureScript, and most importantly, code sharing between the two. Most of my model (business logic) code is in cljc files and it's the same code for the server side and the client side.
When I had to go back and look at some of my old CL code, I found the mutability problematic.
Overall, there is still a warm spot in my heart for CL, but Clojure is quite simply better.
It would be correct if I said that for something like a game CL with its full hot reloading would be an advantage but for web-like where things can be made mostly stateless would not make a difference (namely, in practical terms I do not need to restart things)
The other thing: can I patch something in production without redeploying in Clojure? I think both CL and Smalltalk have this live image feature. Is it possible to hot-reload a stateless function in Clojure without restarting the system?
I have a reason to ask for this since I think it will be handy at times for maintaining my own thing. Not a piece of software with 5 guys behind so it can make a difference in time invested.
You can expose a REPL socket from a running clojure instance in whatever environment you choose. Biff has this as a marketed feature, described on this page: https://biffweb.com/docs/reference/production/
Thanks for the link.
Is this a regular way to deploy?
I mean, I saw there is Leinen or something like that for package management.
But once you run, you could still connect to an app that has been run in the usual way? Seems like a setup on top of it.
Or is is just independent?
It's regular, every production Clojure system has REPL access for devs.
You don't need it often, but when you do, it's invaluable. And the REPL is such a normal thing to use in Clojure, there's no reason not to do it.
This page should give you the answer: https://nrepl.org/nrepl/usage/server.html
I don't think a game changes anything.
You can fully reload everything in Clojure as well.
The only limitation is an existing object instance cannot hook into the reload cycle and upgrade itself at runtime. You need to re-create the instance.
But since Clojure is not object oriented, and if you have such objects they'll be from Java interrop, it's not something that you feel you'll be missing or need.
Yes you can hot patch Clojure in production, but modern deployment practices make that not really something people do, as you run multiple instances anyways, it's easier to swap full instances and be sure everything is in-sync with your repo and CI/CD environments.
What people do is more they use a production REPL to help root cause and debug.
The authors of The Art of Metaobject Protocol would disagree.
> Is it possible to hot-reload a stateless function in Clojure without restarting the system?
Sure. But over the years I learned that I don't want to do that unless I'm debugging something, and I'd never do that in a production system anymore.
Like many other things in CL, they seem nice and shiny, and are sometimes beautifully designed (meta-object protocol!), but in practical day to day usage, especially with production systems, it's better to stick to simpler and more understandable tools, and predictable and repeatable deployments. Even if it's "your own thing" (I've been running my own SaaS for >10 years now). That's why I rarely use multimethods, I try not to be too smart and fancy with my code, I comment and document a lot, use ansible for deployments, and never patch production systems (e.g. every update goes through an ansible deployment).
Agreed. This is also my intuition.
By hot-patching you can make a mess of where things are probably.
Even if it is a bit more work, going through a more normal cycle lets you understand what is going on.
So for what I see from other comments and yours REPL is nice for interactive work and root cause debugging but hot-patching a production system, even if powerful, comes with its own set of problems.
You can even share business logic between backend/frontend AND shell scripts via babashka!
Yes, my gut feeling tells me that sticking to functional + modern platform is safer. Having structure can also be seen as an advantage IMHO.