I’d like to announce Infiltrator.jl, which is intended as complement to the existing debuggers.
What is this?
Infiltrator.jl provides a macro called @infiltrate , which sets a “breakpoint” in a local context (similar to Matlab’s keyboard function). The advantage of this macro over e.g. Debugger.jl is that all code is completely compiled, so the performance overhead should be negligible.
@infiltrate will drop you into an interactive REPL session that lets you inspect local variables and the call stack as well as execute arbitrary statements in the context of the current function’s module. You can optionally supply an argument to @infiltrate (that must evaluate to a boolean) to make it conditional.
Note that you cannot access other functions in the callstack, or step into functions. If you need that functionality, use Debugger.jl or Juno’s debugger.
Installation
pkg> add Infiltrator
Usage
julia> function f(x)
x *= 2
y = rand(3)
@infiltrate
x += 2
end
f (generic function with 1 method)
julia> f(3)
Hit `@infiltrate` in f(::Int64) at none:4:
debug> ?
Code entered is evaluated in the current function's module.
Note that you cannot change local variables.
The following commands are special cased:
- `@trace`: Print the current stack trace.
- `@locals`: Print local variables.
Exit this REPL mode with `Ctrl-D`.
debug> @trace
[1] f(::Int64) at none:4
[2] top-level scope at none:0
debug> @locals
- y::Array{Float64,1} = [0.187253, 0.145958, 0.183677]
- x::Int64 = 6
debug> x.+y
3-element Array{Float64,1}:
6.187252565686353
6.145958004935359
6.1836766675450034
debug>^D
8
julia>
This is great! You’ve covered 90% of my use cases for debugger with this. I’m also impressed with how simple the package is as well - just over 200 lines and basically no dependencies! (I also like the name )
I love the idea. This is a good portion of what people do when use debuggers for exploration. This still requires modifying the files, but it is a step forward.
Does it currently support/or are you planning to support showing the locals in the Juno panes? Are you also considering this as a debugging option in Juno in general (i.e. people could choose to either run the fully interpreted version with all of the flexibilty, or this faster version for just exploring the state of the computation)?
I would be very helpful for usability of low tech debugger users. In matlab you can both modify the code/local variables and still run it full speed between breakpoints. We won’t be there in Julia for a while, so I think it is reasonable to make people choose what they want. Most cases will be of the second type where infiltrator (if I understand it) is the solution. If the UI makes the choice clear (ie high speed exploration vs interpreted full control), then people will no longer be perplexed that the code runs orders of magnitude slower while debugging
Debugging in Julia was an issue, and just to check a variable value inside a function you had to go through the slow debugging process. But not anymore!
This is exactly what I wanted .
Is there a minimum Julia version required? I was able to install in v1.2. In v1.0.4, it is throwing this error:
(v1.0) pkg> add Infiltrator
Updating registry at `~/.julia/registries/General`
Updating git-repo `https://github.com/JuliaRegistries/General.git`
Resolving package versions...
ERROR: Unsatisfiable requirements detected for package Infiltrator [5903a43b]:
Infiltrator [5903a43b] log:
├─possible versions are: 0.1.0 or uninstalled
├─restricted to versions * by an explicit requirement, leaving only versions 0.1.0
└─restricted by julia compatibility requirements to versions: uninstalled — no versions left
Are you by chance using Juno’s/VSCode’s inline evaluation for executing a function that calls @infiltrate somewhere down the call stack? If so, that’s a known problem, and the only workaround is to call your function in the REPL.