Many points were the reasons why I am now using Julia to develop a large-scope full-stack application. Revise (package) allows to evolve the program interactively while preserving the system state. For instance, I can have an instance of a struct in the REPL; I change one of the modules, and the available behaviour of the instance can be immediately tried out without recreating the state. Or, when interactively developing a webserver, I find an error on one of the served pages. I changed the piece of code in the module, and it is immediately reflected when reloaded while keeping the existing state.
System introspection is easy as everything is available from the REPL. Default printing is available for all user-defined types, which can be specialised on a wish. Thus, printing an object or even getting to the precise point in the module call stack with an Infiltrator is always accessible.
One pain point regarding file-based organisation is that, in most languages, every file is within its namespace. In Julia, these things are orthogonal. You can have a single namespace organised over multiple files or multiple namespaces within a single file. This generally makes it easier to navigate a large namespace while not being bothered with making explicit imports, etc., when one is still in the exploratory phase.
I can’t really relate to tree-based exploration. Very few times do I find that the direction I have found is wrong, so I do a git reset to a previous commit. Also, there are a few sunk costs migrating from one approach to another when most of the functions are written to be pure.
Another essential piece for explorative development is types. Although some planning is required, it is generally worth it. In Julia, those are checked at runtime, which nevertheless significantly helps to locate issues quickly when doing test-driven development.