I do a good combination of data science and development.
REPLs are nice, don't get me wrong, but they are by nature single entrance, single exit. You are basically riding shotgun on a single unit test. You get a great view along the way, but the problem solving doesn't scale, nor can it handle situations where you need to consider multiple paths through the code. Writing a good test suite, and knowing just where and how to place debug trace statements are two of my best problem solving skills.
F# hits a really nice sweet spot for this: scripts with an integrated interactive scripting environment, and complete access to a plethora of unit testing frameworks.
That lets you work line-for-line through your code, inspect and analyze each step as needed, edit parameters as wanted, restart and do clean runs through calculations using custom and third party libraries, and also interactively execute any tests/specs you have defined. It's a very tight feedback loop that doesn't compromise any of the long term artifacts you might want in a serious app.
In conjunction with .Nets extension mechanisms and some F# language features the setup lets you fire up a basic script, replace/extend anything from your object graph with new code, write accordant tests, and execute any or all parts of the test as desired in an interactive REPL-like session for problem solving and debugging: all in the same file :)
This flows really nicely with the single pass compiler, keeping things nice and clean so they integrate into the main app once exploratory development is done. Semi-serious typing, functional composition, and dynamic exploration -- it ain't bad.
Once you achieve the right result from the function you are writing, you just add that REPL invocation to your test suite. Then you just re-run your tests from time to time as you change the code further.
>You are basically riding on a single unit test. You get a great view along the way, but the problem solving doesn't scale, nor can it handle situations where you need to consider multiple paths through the code.
Where a REPL starts to fail, I find integration tests start to shine and vice versa.
I see it along the lines of REPLs being helpful for prototyping code. TDD, strong static type systems and proper separation of concerns let you build larger maintainable systems.
Indeed, that's partly what my own testing framework (that I wrote and use on my own private projects) takes advantage of, except in interactive use.
The Common Lisp REPL automatically binds the last expression evaluated to the variable "+". It also automatically binds the value returned from the evaluation of the last expression to the variable "*".
I write code and develop interactively at the REPL with the package under development loaded/running. When the value I expect gets returned from the function or form I'm developing at the REPL, i just evaluate the "test" function (or a variant thereof if extra specificity or features are wanted such as names, doc-strings or tags, etc.), and the forms and expected values are packaged into a test and added to the projects' test repository.
Pretty much all the benefits of TDD, without writing tests up-front or wanting to do red/green (i did allow for the option, but i practically never do in practice), because they're an almost costless artifact of just developing now...
REPLs are nice, don't get me wrong, but they are by nature single entrance, single exit. You are basically riding shotgun on a single unit test. You get a great view along the way, but the problem solving doesn't scale, nor can it handle situations where you need to consider multiple paths through the code. Writing a good test suite, and knowing just where and how to place debug trace statements are two of my best problem solving skills.