And as someone who programs in Clojure, I feel the interactivity is the same. Maybe I'm missing a detail of what he's doing though?
The part you don't have in Clojure (without using a library), is the restart options, but he didn't seem to ever use them, seems he just looked at the error message, and went back to fix the code and re-evaluate his test again, and that would be exactly the interactive flow I would follow in Clojure.
Am I missing something?
In Clojure, you can debug at the REPL, but it doesn't drop you in the debugger by default. You'd need to eval the function as debug first, then it will drop you into the debugger next time the function is called.
And there's no restart system by default, so for example you probably wouldn't retry by choosing restart test from the exception debugger, you'd just re-evaluate the test yourself to have it rerun.
There's a condition restart library, and I played a bit with it, but not enough, I was confused about how to go about choosing options to handle the condition or how to define them.
So the typical flow in Clojure would be:
1. Error thrown
2. Go to line of code that threw error
3. Fix code
4. Eval fixed code
5. Eval the thing that threw the error again (seeing everything pass)
And if you want to observe the state at the place of the error thrown you'd add between 2 and 3: 2.1 Eval function as debug
2.2 Re-eval thing that threw error
2.3 When in debugger inspect all locals and state, find the problem
And then go to 3.I never really looked into if there was a way to make eval as debug default with break on error, then I guess you'd get a very similar flow, except for missing the restart options.
> There's also the typical class change: in CL you can alter a class definition and the existing objects are (lazily) updated
Since Clojure isn't OO, this isn't a 1:1 comparison. But the closest thing to OO is polymorphic facilities, except they don't have state. Anyways, you can update the implementation of the polymorphic methods and it gets picked up for existing types or data that were polymorphic over them.
You can also add more polymorphic methods and those get picked up automatically.
There is a construct that has fields on it, but it's almost never used, so I actually don't remember if it would let you update fields on existing instances, I believe not. In CL can you add/remove fields on the class and the existing instances get updated? What happens to new fields how are they initialized in that case?
> you can't install a Clojure library from the Clojure REPL, right?
Well, you can, but let's say that it's something that easily breaks, so let's call it a "beta" feature. Some people use it effectively and don't seem to have issues, but others seem to always have it not work as expected, so a lot of people restart the REPL most likely when they want to add a lib.
Also, it's not a standard feature of Clojure, instead it's a feature of your build tool, either Leiningen or Tools.deps, and both have a different way to do it. Though tools.deps is the default dependency manager that comes with Clojure now, and its add-lib feature should one day get out of beta and become permanent, probably once they iron out the quirks.
https://practical.li/clojure-staging/alternative-tools/cloju...
yes, and you can even specialize built-in methods so that the update does exactly what you want O_o See update-instance-for-redefined-class. It takes as arguments the added slots, the discarded ones, it's supposed to do the right thing but we can customize it.
You wouldn't get that in Clojure for defining types, since they'd be Java types and then they only get what features the Java runtime allows on types and it doesn't have that one.
But in practice, since Clojure is functional, it's kind of a non-issue.
I should really try CL to be sure, but it seems you'd get 95% or more of the same interactivity in Clojure.
What I can tell you is I find Clojure superior to Emacs LISP in interactivity (which I've used both extensively). Emacs can technically redefine more things inside-out, like it can do the full runtime rebuild from the example link, but because it isn't functional and immutable first, managing the state as you redefine things tends to be more complex, and I find that makes it less interactive, since I need to do a lot of state setup and teardown to get things back to what I want to re-evaluate.
I love writing CL but there’s a reason it’s not enjoying wide usage nowadays, and I definitely wouldn’t go around recommending it to unsuspecting people without heavy caveats.