The article it discusses is a
“Not a monad tutorial”
post, where the interviewee is experienced in C++, Java, Javascript and Python and
turns into Clojure. He wrote about his first impressions with Common
Lisp
here,
where he raises usual concerns that I agree with but IMO that stay
supercifial (“not readable” because of stuff like (format t
"~{~{~a:~10t~a~%~}~%~}" *db*), “huge operators set”, “macros look
promising”…).

Here starts the discussion.

dzecniv On Common Lisp, I agree with the criticisms except

the code was very difficult to read

I find it very easy, always well expressed, with concise
functions. And I find Clojure’s harder, with more
[, { and the same number of other symbols (#, *).

Anyway, I’m in the process of trying to go from python to CL.
The CL ecosystem is quite good nowadays (equivalents of pip, venvs, pyenv, implementations (even
for the JVM or iOS), CI, sphinx, readthedocs, wsgi, setup.py,,…), it’s moving, we can do quite a
lot (awesome list),
it has unique features but yeah, the ecosystem is tiny compared to
clojure’s…

In many ways is it much broader than Clojure, since there is much more
choice. Interpreters, compilers, native code compilers, batch
compilers, compilers targeting
C/LLVM/JVM/ARM/ARM64/x86/x86-64/SPARC64/POWER/…

Clojure on the JVM uses a relatively simple and not very user-friendly
compiler to the JVM. No Interpreter. No mixed use of interpreted and
compiled code. Functions need to be declared before used. Error
messages are exposing the underlying JVM. No TCO. No images. Slow
startup.

The Roomba cleans your home with a CL program.

MagicMurderBagYT

No Interpreter.

Hol up. What about the REPL?

lispm

That’s not an interpreter. A REPL is not the same as a Lisp
interpreter. REPL means read eval print loop. EVAL can be implemented
by a compiler or an interpreter. Common Lisp has both and mixed
implementations with both compiler and interpreter.

A Lisp interpreter is executing Lisp code directly. Clojure does not have an Interpreter.

As you see Lisp comes with a sub-repl in the break. The sub-repl is
just another repl, but in the context of the break. The break could be
done by the debugger when it sees an error or by user code - as above.

Now we ask the interpreter for the current lambda expression:

CL-USER 30 : 1 > :lambda
(LAMBDA (A B) (+ (PROG1 2 (BREAK)) (* A B)))

Above is actually Lisp data. Code as data.

Now I’m changing the + function in the code to be expt,
exponentiation. To be clear: I’m changing in the debugger the current
executed Lisp function on the Lisp level. We take the third element of
the list, and then the first one of that. This is the + symbol. We
change it to be expt. * holds the last evaluation result of the REPL.

What did we see? We saw that the interpreter uses actual Lisp
code. Lisp code we can change with Lisp code in the debugger.

A second example.

What can we do with that for debugging? Well, we can for example write
our own evaluation tracer. The Evaluator prints each expression and
its result nicely indented, while walking the expression tree and
evaluating subexpressions. Remember: this is now user-level code. The
example is from CLtL2. You will also see that LispWorks can freely mix
compiled and interpreted functions. The function COMPILE takes a
function name and compiles its Lisp code to machine code.