What most answers here are missing is pointing out the unique difference between a LISP REPL and an interpreter console/shell kind of thing, which is that it fits seamlessly into the languages design. I often see Javascript devs quite unimpressed by a REPL - "I have a console, too". And while Javascript admittedly comes close, its just not the same.
What makes LISP REPLS special is precisely that there is nothing special about them.
There are no extra ceremonies, caveats, or layers that turn a LISP into a REPL. Its conceptually a fourliner, merely replacing the compilers input of parsing text files with reading user input, while providing access to a modified environment after each step. This is possible not because of the REPL, but because of how LISP is designed. It understands going into packages, importing stuff, inspecting values all naturally, not via some "interactive" mode / layer. You are speaking to the compiler directly and it understands your language. For this reason it is much more reliable and natural to embed a REPL in your development process in LISP, than in other languages.
The article is not trying to sell you on Lisp, in its first sentence it clarifies, that it is written for people who were "asking for advice on how to learn Common Lisp"...
I wouldn't use it. The footgun is imaginary. I use Datomic for ten years and I can assure you that I never stepped on it. As a Datomic user you see transactions as clean small diffs, not as complicated multi step processes. This is actually much more pleasant to work with.
This is also good to hear! I'm not sure whether I'd call it a "footgun" per se--that's really an empirical question about how Datomic's users understand its model. I can say that as someone with some database experience and a few weeks of reading the Datomic docs, this issue actually "broke" several of the tests I wrote for Datomic. It was especially tricky because the transactions mostly worked as expected, but would occasionally "lose updates" or cause updates intended for one entity to wind up assigned to another.
Things looked fine in my manual testing, but when I ran the full test suite Elle kept catching what looked like serious Serializability violations. Took me quite a while to figure out I was holding the database wrong!
In traditional databases, only the database engine has a scalable view of the data - that’s why you send SQL to it and stream back the response data set. With Datomic, the peer has the same level of read access as the transactor; it’s like the database comes to you.
In this read and update scenario, the peer will, at its leisure, read existing data and put together update data; some careful use of compare and set, or a custom transaction function, can ensure that the database has not changed between read and writes in such a way that the update is improper, when that is even a possibility - a rarity.
At scale, you want to minimize the amount of work the transactor must perform, since it so aggressively single threaded. Off loading work to the peer is amazingly effective.
You could include two transaction functions that constrain a transaction to different properties about the same fact and then alter that fact. I don't know of a practical usecase or that I ever encountered that, it would be extremely rare IME.
What? If anything, we have a "do-it-right" mentality :) The Clojure library ecosystem is very rich with new libraries coming out every week. We also reuse the rich Java library ecosystem to a large degree.
I'm with Clojure for 10+ years and I don't "often end up writing custom code for a generic feature". Its quite the opposite. Clojure is a language that has hundreds of extremely well composing generic functions built in, that operate on a very rich set of first class immutable datastructures.
Whatever Clojure you base your impressions on is very different from the one I know and use...
What makes LISP REPLS special is precisely that there is nothing special about them.
There are no extra ceremonies, caveats, or layers that turn a LISP into a REPL. Its conceptually a fourliner, merely replacing the compilers input of parsing text files with reading user input, while providing access to a modified environment after each step. This is possible not because of the REPL, but because of how LISP is designed. It understands going into packages, importing stuff, inspecting values all naturally, not via some "interactive" mode / layer. You are speaking to the compiler directly and it understands your language. For this reason it is much more reliable and natural to embed a REPL in your development process in LISP, than in other languages.