In R, I could put a browser() into any where I want. It gives me a REPL so that inspection, changing variable values, etc. are possible. It makes debugging very easy and convenient.
Ideally, if we could do it in Julia, it would be like:
function xxx()
"""
codes that are 100% fine
"""
browser() # REPL for inspection and making arbitrary adhoc changes
"""
codes that may have problems
"""
end
Is it possible in Julia?
Right now I’m using ASTIntepreter2.@enter(), which allows me to step into a function. However, everytime I have to start at the beginning of the function rather in the middle, or being conditional…
My understanding is that these tools are under development. I don’t really know much about how they work or what features they will ultimately include. Nonetheless, you might look into the debugger utility discussed in this thread: [ANN] Rebugger: interactive debugging for Julia 0.7/1.0 - #10 by tim.holy
I do want to understand whether this is really something we want or whether there might be a better way. So some questions:
how often do you know in advance which method is problematic? Most often I start at the top and work my way into the call chain, discovering as I go where the problem lies. Hence “stepin” functionality typically covers my needs.
for those cases where you do have a suspect, do you really want to edit the source code to insert that browser line? What about just saying breakon(xxx), where xxx is the name of your function, at the Julia prompt?
In my cases (I’m not the OP), I know the culprit in advance most of the time (it’s the function I’m currently working on). Regarding your second point. Both would be useful . If I had to choose though I’d go with breakon.
Sometimes, it’s in the 8500th iteration of a loop. Or maybe somewhere after the loop. Then stepping becomes tedious.
Not at all (correction: I agree stepping is tedious in traditional debuggers, but less so in Rebugger); step to the method and then edit the line that Rebugger provides you to
rebug> @eval SomeModule let (vars...,) = getstored(uuid) begin
# some code that Rebugger put here for you
for iter = 1:10000
# some other code Rebugger put here
# Now you add this:
if iter == 8500
@show all_the_vars...
end
# yet more code Rebugger put here
end
...
This is part of why I wonder if breakpoints are that important: since you interact with Rebugger through the normal REPL, a breakpoint isn’t some special “thing”, its just you tweaking the code to do whatever you want. Since you can edit code while effectively in debug mode you can do anything you want.
If it’s in the 8500th call to the method from some external method, then you can’t entirely do it at the REPL; you might have to add a if condition throw(SomeError()) end and then Meta-s on the caller. After that, you’ll have access to the direct inputs that caused the error to be thrown.