Reputation: 495
When I'm prototyping and debugging code in Matlab, I can run a script and immediately inspect and edit all variables in that script when it stops running (either successfully or due to failure).
In Julia, variables inside a loop are locally scoped. While this is fine once I'm satisfied I have things working, I can't inspect variables in the REPL. The only way I can think to get around this is to list every variable in the loop as a global. Then I would have to edit that line every time I change a variable name or introduce a new one. Adding/changing variables is quite common when I'm experimenting and not fully sure what I'm doing yet. Is there a better way to do this?
Upvotes: 0
Views: 238
Reputation: 196
I came up with the following very basic and simple macro. The idea is to modify the expression by adding a print statement for every assignment.
To use it, just add @add_print before the function or block of expressions you want.
However, the best solution would be using the Gallium debugger
walk(ex) = nothing
function walk(ex::Expr)
for i in 1:length(ex.args)
subex = ex.args[i]
#println(subex)
walk(subex)
if isa(subex, Expr) && subex.head in Set([:(=), :(+=), :(-=), :(*=), :(/=)]) && ex.head == :block
#println(subex)
line = "line unknown:"
if i > 1 && ex.args[i-1].head == :line
line = "line $(ex.args[i-1].args[1])"
end
var = string(subex)
ex.args[i] = :(
begin
$subex
println($line)
println($var, " -> ", $(subex.args[1]))
end
)
elseif ex.head == :block && isa(subex, Symbol)
ex.args[i] = :(
begin
println($subex)
$subex
end
)
end
end
end
macro add_print(ex)
walk(ex)
ex
end
Demo:
@add_print function binary_search(v, val)
if v[1] > val || v[end] < val
return 0
end
left = 1
right = length(v)
while left < right
mid = div(left + right, 2)
if v[mid] < val
left = mid + 1
else
right = mid
end
end
left
end
binary_search([1, 3, 4, 5, 7, 9], 4)
julia> binary_search([1, 3, 4, 5, 7, 9], 4)
line 5
left = 1 -> 1
line 6
right = length(v) -> 6
line 8
mid = div(left + right,2) -> 3
line 12
right = mid -> 3
line 8
mid = div(left + right,2) -> 2
line 10
left = mid + 1 -> 3
3
Upvotes: 1