-
Notifications
You must be signed in to change notification settings - Fork 218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scope question #545
Comments
Why not just replace every symbol in the body of every function by a unique julia> using MacroTools
julia> mapping = Dict{Symbol, Symbol}()
Dict{Symbol,Symbol} with 0 entries
julia> MacroTools.postwalk(x -> x == :x ? (newx = gensym(x); mapping[x] = newx; newx) : x, :(x = 1))
:(##x#358 = 1)
julia> mapping
Dict{Symbol,Symbol} with 1 entry:
:x => Symbol("##x#358") This is one approach anyways. |
Thanks, @mohamed82008. This problem becomes complicated when we re-use variable names between child and parent scopes. Consider the following example using Turing
@model gdemo(x) = begin
s ~ InverseGamma(2,3)
m ~ Normal(0,sqrt(s))
z ~ Bernoulli(0.5)
x ~ Normal(m+1, sqrt(s)) # x1
let
if z == 1
x ~ Normal(m+1.5, sqrt(s)) # x2
else
x ~ Normal(m+2, sqrt(s)) # x2
end
end
for i=1:5
x ~ Normal(m+3, sqrt(s)) # x3
end
return s, m
end
Here we re-used variable names Related: #484 |
This seems to work: using MacroTools: @capture
function replace_vars(expr)
mapping = Dict{Symbol, Symbol}()
_find_vars(expr, mapping)
_replace_vars(expr, mapping)
expr
end
function _find_vars(expr, mapping)
if expr isa Expr
for i in 1:length(expr.args)
x = expr.args[i]
if (@capture(x, (V_ = R_)) || @capture(x, (V_ ~ R_))) && V isa Symbol
if !haskey(mapping, V)
newvar = gensym(V)
mapping[V] = newvar
end
_find_vars(R, mapping)
elseif @capture(x, for V_ in R_ body_ end | for V_ = R_ body_ end) ||
@capture(x, let V_ = R_; body_ end | let V_; body_ end) ||
@capture(x, f_(args__) = body_ | function f_(args__) body_ end)
replace_vars(x)
else
_find_vars(x, mapping)
end
end
end
expr
end
function _replace_vars(expr, mapping)
if expr isa Expr
for i in 1:length(expr.args)
x = expr.args[i]
if haskey(mapping, x)
expr.args[i] = mapping[x]
else
_replace_vars(x, mapping)
end
end
end
expr
end julia> expr = :(@model gdemo(x) = begin
s ~ InverseGamma(2,3)
m ~ Normal(0,sqrt(s))
z ~ Bernoulli(0.5)
x ~ Normal(m+1, sqrt(s)) # x1
let
if z == 1
x ~ Normal(m+1.5, sqrt(s)) # x2
else
x ~ Normal(m+2, sqrt(s)) # x2
end
end
for i=1:5
x ~ Normal(m+3, sqrt(s)) # x3
end
return s, m
end);
julia> replace_vars(expr)
:(#= REPL[5]:1 =# @model gdemo(##x#361) = begin
#= REPL[5]:1 =#
#= REPL[5]:2 =#
##s#358 ~ InverseGamma(2, 3)
#= REPL[5]:3 =#
##m#359 ~ Normal(0, sqrt(##s#358))
#= REPL[5]:4 =#
##z#360 ~ Bernoulli(0.5)
#= REPL[5]:5 =#
##x#361 ~ Normal(##m#359 + 1, sqrt(##s#358))
#= REPL[5]:7 =#
let
#= REPL[5]:8 =#
if ##z#360 == 1
#= REPL[5]:9 =#
##x#362 ~ Normal(##m#359 + 1.5, sqrt(##s#358))
else
#= REPL[5]:11 =#
##x#362 ~ Normal(##m#359 + 2, sqrt(##s#358))
end
end
#= REPL[5]:15 =#
for ##i#363 = 1:5
#= REPL[5]:16 =#
##x#364 ~ Normal(##m#359 + 3, sqrt(##s#358))
end
#= REPL[5]:19 =#
return (##s#358, ##m#359)
end) The second branch of the if statement of |
Hi @mohamed82008, could you:
Related: Forbid variables with same name #146 |
Is anyone aware a package/way for extracting scoping structure of a Julia function? For a special reason, I need to implement a macro that can rename variables in child scopes so that variables that exist in both parent scope and child scopes are renamed to different names.
@mohamed82008 @ChrisRackauckas @MikeInnes @StefanKarpinski
The text was updated successfully, but these errors were encountered: