Interactive prototyping workflows

I followed this on a flight of fancy. In my startup.jl:

if isinteractive()
# https://discourse.julialang.org/t/interactive-prototyping-workflows/133265/30
import REPL
struct InteractiveMode end
Interactive = InteractiveMode()
(::Base.IncludeInto)(script::String, ::Val{Interactive}) = begin
  let m = Module(Symbol(script))
    Base.include(m, script) # not the module-specific include
    REPL.activate(m)
  end
end
(::Base.IncludeInto)(script::String, interactive::InteractiveMode) = include(script, Val(interactive))
end

I tried to make include(script; interactive=true) work but I couldn’t get the magic of Val() to work with keyword arguments. I guess you don’t really need the type-based multiple dispatch, that was the flight of fancy part.

Demo:


julia> run(`cat t.jl`);

A = 1
display(A)

julia> include("t.jl", Interactive)
1

(Main.var"t.jl") julia> A
1

(Main.var"t.jl") julia> A = 8
8

(Main.var"t.jl") julia> Main.REPL.activate(Main)  # quit

julia> A  # namespace was not polluted
ERROR: UndefVarError: `A` not defined in `Main`
Suggestion: check for spelling errors or missing imports.

I’m not sure if I’ll like it, yet. REPL.activate doesn’t nest; rather, it simply updates a global pointer to what module you’re interacting with, so to step out of it you have to explicitly step back to the previous module you were in; and also you need to call it Main.REPL.activate when you’re inside the other module. I wish I could Ctrl-D to get back to Main.

I’m not sure either how this interacts with garbage collection. It’s neat though!

I feel like this is worth branching into another thread if you want to continue developing this.