and the benefit of lisp comes from the fact that every expression is fully delineated by parentheses, so you don't need to select any text, find the start or the end of any syntactic construction, you just eval the form you're standing at and see the result
or just as easily you can wrap that form, bind the locals to test values and eval that to see what changes
All that said, 90% of the time you still just eval a bit of a code to see what happens and that's the same between the two languages.
(you can theoretically pass "reload": true (or similar option) in launch.json for auto reload, tho I haven't felt the need to use that in my workflows.)
The cycle is:
1. Write production code.
2. Write some dummy code in the same file (fake data, setup).
3. Evaluate that dummy code. See what happens.
4. Modify code until satisfied.
Your feedback loop is now single digit seconds, without context switching. It's extremely relaxing compared to the alternatives (rerunning tests, launching the program with flags, what have you)."Typical REPL" workflow: Have one editor open, have one REPL open, have one terminal open that runs the application. One change is typically: Experiment in the REPL window, copy-paste into your editor, write tests, restart application (lose all state), setup reproduction state, test change. Or something like this.
In a Clojure REPL workflow, you'd do something like: Have one editor open, this starts the REPL and often the application in the background too. One change is typically: Edit code, evaluate that snippet of code (which sends it to the REPL and the running application), write tests, evaluate them too in the editor, if you're happy, hit CTRL+S and you're done. Application still has the existing state, no restarts needed and you essentially never have to leave the editor window/pane.
Of course, others might have slightly different workflows, but for myself and many (most?) other Clojure developers I've observed in the wild, this is pretty much the standard.
* Clojure is built different in terms of hot code reloading
* the REPL is its own application process in languages Ruby or Python, but in Clojure it’s sortof a client for the system
Is that right? Is there more to it?
So in a JavaScript server, you might have the database connection set in some config/thing you pass around to request handlers to use, and if you change a request handler, you typically stop the entire application, then start it again. Then the database connection (and the entire config in fact) would need to again connect.
In a Clojure application, first you either start the repl from the server, or start the server from the repl, then you might instead keep the database connection in an "atom" that you keep around for as long as you have the repl/server running. And instead of restarting the process when you change a handler, you'd only change the handler.
And yeah, the libraries and ecosystem at large is built with this (mostly) in mind for everything. The language also supports this by letting you "redefine" basically anything in a running Clojure application, which would be harder in other languages.
I've done some experiments years ago for doing the same in JavaScript, and it kind of works, but every library/framework in the ecosystem is not built with this in mind, so you'll be writing a lot of your own code. Which, now with LLMs, maybe is feasible, but can't say it was at the time exactly.
The fun way to get a feel for lisp machines is emacs, it's so easy to fall of a language and especially hand-coding in a language if you don't have to.
Personally, I find waiting more than 200ms unacceptable and really < 50ms is ideal. When the feedback is very small, it becomes practical to save the file on every keystroke and get nearly instantaneous results with every input char.
As in restarting the entire program and re-running every subsequent query/state changing mechanism that got you there in the first place, being careful not to accidentally run other parts of the program, setting it up to be just so, having to then rewrite parts if you then want to try something somewhere else?
Perhaps I'm misunderstanding you, because that sounds horrible unless you're scripting something small with one path.
The whole point of the REPL is that you evaluate whatever functions you need to get into your desired state and work from there. The ad hoc nature of it is what makes you able to just dig into a part of the code base and get going, even if that project is massive.
> Personally, I find waiting more than 200ms unacceptable and really < 50ms is ideal.
Calling a function on a running program takes microseconds; you're not restarting anything.
An example of me solving an Advent of Code with clojure and repl. You can see i never interact with the repl directly, I just send code to it via my editor and get results inline.
1. REPL is automatically compiled into running systems 2. Great hot-reloading support
So it's generally very easy to "poke" at a running system, and the whole dev process assumes you will do this.
TBH, these days it is largely possible in a C++ debugger. Less so 10 years ago, though.
there's a detailed explanation here: https://youtu.be/Djsg33AN7CU?t=659
Not even close.
I think debuggers are just better anyways. When I got into the weeds trying to do this interactive REPL workflow on an actually running webapp it was a big mess. You have to write custom code all the time to basically capture data and save it into global variables, so that you can inspect them (as opposed to a debugger where you can just set a breakpoint and inspect all the variables in the middle of the precise spot in the request-response cycle).
I think maybe this was ahead of its time when it came out in 2008 or got popular in 2010-2015, but nowadays I am not seeing what's specifically more productive about the Clojure REPL than the interactive development experiences available in Laravel, Python, JS, etc.
If it was like a choice, Clojure has my favourite reverse debugger flowstorm which also exposes the runtime information of your program programmatically
So you can code cool visual programs against the runtime values of your first program
Like I built an emulator at work that simulates our program in production as a flowstorm plugin then you can step through the program frame by frame
I love taking the guess work out of production issues, just get the computer to show you exactly how everything went down
It's like a rewindable movie made up of thousands or millions of frames of the execution of your program
That's where "code is data" shines and you can manipulate it at will. For the rest, I'm glad I have "code as text" in my editor, where I can see and inspect it far more easily than one line at a time.