They have to write reams of unit testing code , mocking and faking the world just to see some code executed.
Many problems are only solvable with compiled languages, for performance, correctness, or other non-functional considerations. Many people are first taught on compiled languages, and bring those approaches to dynamic languages. The popular dynamic languages, in their standard/common toolchains, do not have robust repl support (looking at you Python and Javascript). The absence of a robust repl workflow means people who are exposed to it in those languages aren't really impressed by it. Really too bad.
The problem with the way we're taught (or I was taught, circa 2000), was that it was still in the batch-oriented mode: "Gather all your source files, and run them all through the compiler together." "But I only changed one thing." "That's fine, `make` will do the right thing for you." "But I also have to close the program." "Well, yeah, there are ways around that but we won't teach you, maybe your future coworkers or employers will."
Your work over the years on Clojure is so deeply appreciated and my post was also to some degree coming from a place of lament that more people don't know about it and benefit from it. Thank you for it.
In fact Mesa had one on XDE, which was improved in Mesa/Cedar, because the team wanted to cater their environment to the Lisp and Smalltalk developers at Xerox.
Wirth built on top of this when he designed Oberon, where the OS only supports dynamic linking, and every public exports from a module can be used on Oberon's REPL as a command.
Although many people aren't aware of this, Eclipse always had a crude REPL via Java Worksheets, which allowed to execute Java expressions and saving those sessions on the workspace. This trances back to Smalltalk transcripts and Visual Age for Smalltalk heritage.
Eiffel also offers a REPL like experience in Eiffel Studio via the MELT VM.
.NET had Linqpad for quite some years, until Visual Studio got interactive C# and F# shells, and immediate debug mode goes back to the VB days of yore.
So there are plenty of options with compiled languages, but like with graphical debuggers, teaching is lacking on the availability of such tooling.
The place I would start from a critique perspective is around lifecycle. Python has encouraged carelessness and overwork at module load and init time, and there aren't common protocols (that I have seen) that involve standing up a graph of objects across an application after a single module reload. So when you reload a single module and the names in the module now point to different data and code elements, all the downstream dependencies on those names have to change as well, and Python doesn't have patterns for organizing and managing at that level.
This also impacts runtime introspection, which is a key benefit of a repl oriented language. One implication is that there is not at all a pattern of "repling into" a running python application to poke around and see what is going on. To most python programmers this is a foreign concept.
Related others involve code style, and implicit vs explicit ways of referring to and moving data around, which also impacts runtime whole system introspection.
Python has all the pieces to have a very nice repl-first programming model, but lacks patterns for key parts of that- explicitly standing up the graph of live objects, and using a repl to interact with a live system with live objects.
Hope that makes sense.
In short, the Python process has to restart to take changes in, and you loose your objects in the REPL. The Lisp process doesn't and is built to (lazily) update your objects to reflect structure changes (such as if you deleted a class slot). I particularly like the Lisp way for unit tests or the web.
Here is a nice example of REPL driven development with Smalltalk.
https://avdi.codes/in-which-i-make-you-hate-ruby-in-7-minute...
1. mess around with some program, echoing things to it and looking at outputs
2. up-arrow in shell, edit previous experiment
3. repeat, adding more onto pipeline, until happy
4. save the good version to a script, eg echo "!!" > foo
5. add a #! line and chmod +x to promote it to a command- No graphical display
- No support for displaying interactive structure data (Lisp Machines REPL/commercial Common Lisp/modern notebooks)
- No debug-break, fix, redo workflow
- No partial selection of command statements and "Do this"
- No interactivity with running graphical applications and scripting them (via COM, DLLs, OS IPC)
I've read this guide several times over the past few years, watched a bunch of the videos and I still find myself stoping/starting the repl very often because it feels difficult to keep the current state of the environment in my head, or something isn't updated as I expected, there's an error I can't decipher in the REPL that the compiler gives better info on. I feel I need to restart constantly, it's still my main workflow. I'm not sure what it is that's not clicking for me, but I keep trying. Either way, I'm no worse off than with my C# workflow.
Ditto with other langs, I just started with Spring Boot & Kotlin & geez, Spring annotations are poison chalice material. Googling how to debug spring leads you to 'just turn on debug logs' which dont tell you 1/1000 of what you'd need to know to debug annotation issues.
That sounds great! I’m envisioning something that for each loaded namespace would show:
- fns that match saved files
- fns that differ:
- newer in file / not in REPL
- newer in REPL / not in file
I guess that would have to be an IDE-level thing, since it needs to know about file changes and REPL contents.A namespaced list of all public var names can be thrown together pretty quickly, but it seems less helpful:
(->> all-ns (ns-name) (map (juxt identity clojure.repl/dir)) (into {}))
(I’m on mobile so I haven’t checked that!)
1. Unless you strictly design functions that are decoupled from any type of UI (such as your back-end "business logic"), it's not straight forward to do REPL driven development on its own.
2. If you're going to go down the path of using the REPL, you might be inclined to do TDD instead because now your efforts are saved to repeatable tests rather than a short lived REPL.
Despite being HNs favourite paradigm, functional languages really are an obscure to most people.
As soon as there is a (convenient, useful) REPL for Java or c#, it will get picked up.
I know Java added a repl a few versions ago, so maybe we will start to see this in the Java world.
Additionally, both languages you listed (Java and C#) are batch-oriented. They assume you're compiling large units of code (at least a whole source file, which in Java means the entire class and all its methods and constructors). Translating that to a REPL is challenging. You now have to leave class definitions open (which is not the normal Java behavior, a class cannot be altered without jumping through hoops outside its initial definition). So you make those hoops available via special REPL-only constructs, your REPL is no longer a Java REPL, it's a partial-Java REPL with additional things.
My primary REPL experiences have been with these languages: Python, Common Lisp, Erlang, Matlab.
2 of those are functional (as a primary part of their design, Common Lisp is multi-paradigm). Python has some functional elements, but is an OO/imperative language. And Matlab (at least when I used it) was definitely an imperative language.
But the thing they all have in common is that nearly every line of code could be moved between the REPL and a source file without alteration (Erlang is deficient here in that you can't define functions in the same way in the REPL as in the source code, and I think Matlab had the same issue but it's been 15 years).
Another thing that languages with a good REPL tend to have is a general trend towards being expression-oriented rather than statement oriented. What's the return value of an if statement in Java or C#? It doesn't have one, how would you interact with that in a REPL, then? In Common Lisp, if expressions return a value (the result of evaluating either the true or the false branch).
It's not mainstream, so one knows how to. Basically somebody needs to show people how repl driven development works, and will be useful.
May be YouTube tutorials or gifs as to how to do this.