I spent a few days testing out the new version of Flexible Julia and here are my thoughts on it and what I feel are still missing.
Thoughts regarding Hot swapping:
Interesting concept, it does mean that code takes a long time to write, since it is updating on the fly. Which I am not quite sure is really what you want.
Maybe make it optional to auto-update like that? I think I would prefer to have a shortcut I can use to update either the function I am in or the entire file rather than it happening automatically.
I think hot swapping has some of the core elements of the debugging experience that I am used to from python, but it is not the same and I am still a bit unsure how to actually use it effectively.
The way I understand it in python is that you have the console window that you can write whatever you want into while a session is ongoing. However, in python, the code in your files does not actually hotswap while a session is started. That means that I can change a file however I want according to what I see in the debugger without contaminating my current session. And then if I want to actually update a function or a variable I just put it into the console and it updates it. This way I can very quickly change a parameter I realized I did not set correctly at the beginning when starting the debugging session or make any other changes I want. Thus my debugging session becomes extremely interactive and explorative.
Hot swapping in julia seems to also enable interactive and explorative debugging, but so far I have not found a good way to really debug with it.
My biggest pain points when debugging in julia
-
Every time I step a line in julia, the julia window changes back to Data tab (rather than the variable tab) - There is likely an easy fix for this, but so far I have not found it.
-
Julia debugger is very slow to start. (From python I am used to my debugger starting in less than a second, and because of this my development process involves restarting sessions often. In julia this approach is severely slowing me down in my development. Partly this is probably me that needs to change my development style and generally just do less restarts. However this is hard since I find that the Julia debugger disconnects more easily than the python debugger and since the interactive debugging is much harder in Julia I am still forced to restart a lot.)
-
Julia debugger fails to start sometimes:
Starting Julia debugger...
[Julia] === Julia Debug Bootstrap ===
[Julia] Julia version: 1.12.5
[Julia] Process ID: 29157
[Julia] Working directory: /home/tue/Projects/JuliaProjects/Glimb
[Julia] Loading IPC channel...
Failed to start debugger: Failed to launch Julia DAP server: Failed to connect to DAP server after 15 attempts
The only way to fix this seems to be to restart my IDE
- If I debug-step over a function that causes julia to crash, I would love for julia to take me to whatever line in my code that julia crashed on. Also the debugging message I am receiving are often unhelpful and filled with useless information. Here is an example:
Starting Julia debugger...
[Julia] === Julia Debug Bootstrap ===
[Julia] Julia version: 1.12.5
[Julia] Process ID: 33946
[Julia] Working directory: /home/tue/Projects/JuliaProjects/Glimb
[Julia] Loading IPC channel...
[Julia] [ Info: FlexibleIPC: Connected to IDE on port 43881
[Julia] IPC channel loaded.
[Julia] Loading IDE display hook...
[Julia] [ Flexible Julia IDE integration active ]
[Julia] IDE display hook loaded.
[Julia] DAP mode enabled for display hook.
[Julia] Loading Sockets...
[Julia] Loading DebugAdapter...
[Julia] All dependencies loaded.
[Julia] Activating project at `~/Projects/JuliaProjects/Glimb`
[Julia] Activated user project: /home/tue/Projects/JuliaProjects/Glimb
[Julia] Attempting to listen on port 39997...
[Julia] Listening on port 39997
[Julia] Waiting for IDE connection...
Connected to Debug Adapter
[Julia] IDE connected, creating debug session...
[Julia] Debug session created, running...
[Julia] Activating project at `~/Projects/JuliaProjects/Glimb`
â–¶ Script is executing in COMPILED (fast, stdlib not debuggable) mode
Breakpoints are active. Will pause when hit.
Debugger stopped: step
Debugger stopped: step
[Julia] starting reading 0.015059 seconds (1.41 k allocations: 967.219 KiB)
[Julia] Debug session ended with error:
[Julia] UndefVarError: `S0` not defined in `Main`
[Julia] Suggestion: check for spelling errors or missing imports.
[Julia] Stacktrace:
[Julia] [1] #invokelatest_gr#232
[Julia] @ ./reflection.jl:1295 [inlined]
[Julia] [2] invokelatest_gr
[Julia] @ ./reflection.jl:1289 [inlined]
[Julia] [3] lookup_var
[Julia] @ ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:5 [inlined]
[Julia] [4] lookup(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, node::Any)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:36
[Julia] [5] step_expr!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, node::Any, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:597
[Julia] [6] step_expr!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:627
[Julia] [7] finish!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:14
[Julia] [8] finish_and_return!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:30
[Julia] [9] evaluate_call!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, fargs::Vector{Any}, enter_generated::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:290
[Julia] [10] evaluate_call!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, call_expr::Expr, enter_generated::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:256
[Julia] [11] evaluate_call!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, call_expr::Expr)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:249
[Julia] [12] eval_rhs(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, node::Expr)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:406
[Julia] [13] step_expr!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, node::Any, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:564
[Julia] [14] step_expr!
[Julia] @ ~/.julia/packages/JuliaInterpreter/j9HeJ/src/interpret.jl:627 [inlined]
[Julia] [15] next_until!(predicate::Any, interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:102
[Julia] [16] _next_line!
[Julia] @ ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:187 [inlined]
[Julia] [17] next_line!(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, istoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:184
[Julia] [18] debug_command(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, cmd::Symbol, rootistoplevel::Bool; line::Nothing)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:498
[Julia] [19] debug_command(interp::JuliaInterpreter.RecursiveInterpreter, frame::JuliaInterpreter.Frame, cmd::Symbol, rootistoplevel::Bool)
[Julia] @ JuliaInterpreter ~/.julia/packages/JuliaInterpreter/j9HeJ/src/commands.jl:478
[Julia] [20] our_debug_command(debug_engine::DebugAdapter.DebugEngines.DebugEngine, cmd::Symbol)
[Julia] @ DebugAdapter.DebugEngines ~/.julia/packages/DebugAdapter/6PfG9/src/DebugEngines.jl:246
[Julia] [21] run(debug_engine::DebugAdapter.DebugEngines.DebugEngine)
[Julia] @ DebugAdapter.DebugEngines ~/.julia/packages/DebugAdapter/6PfG9/src/DebugEngines.jl:335
[Julia] [22] run(debug_session::DebugAdapter.DebugSession, error_handler::Nothing)
[Julia] @ DebugAdapter ~/.julia/packages/DebugAdapter/6PfG9/src/packagedef.jl:162
[Julia] [23] run
[Julia] @ ~/.julia/packages/DebugAdapter/6PfG9/src/packagedef.jl:60 [inlined]
[Julia] [24] start_dap_server(base_port::Int64, max_attempts::Int64)
[Julia] @ Main /tmp/julia_dap_bootstrap_11940535368932068447.jl:131
[Julia] [25] start_dap_server(base_port::Int64)
[Julia] @ Main /tmp/julia_dap_bootstrap_11940535368932068447.jl:102
[Julia] [26] top-level scope
[Julia] @ /tmp/julia_dap_bootstrap_11940535368932068447.jl:147
[Julia] [27] include(mod::Module, _path::String)
[Julia] @ Base ./Base.jl:306
[Julia] [28] exec_options(opts::Base.JLOptions)
[Julia] @ Base ./client.jl:317
[Julia] [29] _start()
[Julia] @ Base ./client.jl:550
[Debugger] Connection to debug adapter lost.
[Julia] Done reading
I would expect to be able to read at the bottom of this message essentially what failed and where. However there is nothing useful for me in this debugging message at the bottom and I have to scroll up and eventually I find this:
[Julia] Debug session ended with error:
[Julia] UndefVarError: S0 not defined in Main
Which is obviously the information I want, except it does not have a line number associated with it, so I will have to manually try and search my code for where this variable might be used
Overall flexible Julia seems like the best debugging environment for Julia, but it still falls short of debugging in many other languages.
Finally, thank you for developing this @madppiper I think it is sorely needed!