For what it's worth, IPython's "autoreload" magic and Julia's "Revise" package get you _closer_ to what the author describes. In both cases, one can define functions/classes/structs in a file/module, load it in a repl, create objects etc, modify the file and have the changes propagate through to live objects
Closer but still so far. As soon as you have more than one module in Python it completely falls apart, despite any autoreload magic. It just isn't the same at all as REPL based programming. In Lisps you can write your entire program with an instance and a REPL running the entire time. No restarting the instance required. It works because it's just how Lisp works. A REPL is a trivial thing you can write yourself that runs in the same instance.
Whenever I think about it I can't quite put my finger on exactly what Python would need to make it the same. It's something to do with the way imports and namespaces work, though.
> Whenever I think about it I can't quite put my finger on exactly what Python would need to make it the same. It's something to do with the way imports and namespaces work, though.
Python has a fundamentally broken module system, and Python 3 did nothing to fix it:
You can also add breakpoints which automatically occurs when exceptions are raised. Which is similar to the breakloop functionality mentioned in the article.
Yes, running pytest with the --pdb flag will drop you into the debugger on an unhandled exception which gets a comparable workflow but it's not quite the same as, a) writing tests to file first is not repl-driven development, and b) you generally have to think about doing it first.
In an ideal repl-driven world you could write the test in the repl entirely and commit it to disk once you're ready.
True, but running the %debug magic command in IPython immediately after an unhandled exception drops you into the debugger at the point of the raised exception, complete with the full interpreter state including the stack. It doesn’t permit edit-and-continue but you can still evaluate expressions (including calling any function) to explore what went wrong without having to recreate the situation inside an explicit pdb session.