Test-driven development as a discipline emerged from the Smalltalk community, and I don't think that's an accident. I think it's a formalization of the way that Smalltalk and Lisp programmers naturally tended to work.
I generally start on something by making a naive model of what I'm trying to accomplish and interrogating it. In successive iterations, I modify the model and the interrogations in the direction of what I need it to be, discovering details along the way.
I'd say that a majority of my actual activity is testing. That's one reason I prefer to interact with a repl from a file: because I want a record of my interactions. I want to be able to do them again and again.
The difference between that record and formal tests is a simple matter of copying the trail of my interactions into a test framework, and that, too, is how I normally work: make model; test it with interactions; keep the interactions around for later.
As I make progress, the models turn into data structures, and the interactions turn into functions and tests.
It may also be faster to find an issue in the REPL, using various tracing tools ("hm, this function returns the wrong thing when I feed it X, let us enable tracing on a few things and see if anything stands out", followed by "aha, that other function over there is actually the problem, let me add some test cases, so we don't have a regression there").
None of these are impossible without a REPL, but may require extensive modification of the source and a recompilation to get the same effect (followed, probably, by either converting your tracing to debug logs, guarded by a verbosity flag, or by painstakingly track down each print and rip it out again).