I want to take an expression like
:(structOne.a[I] = tanh(structTwo.b[I]))
and replace all the composite values with other variables so I can make a function like
function f(I,a_new,b_new) # can't use composite values here
a_new[I] = tanh(b_new[I]) # original expression with new symbols inserted
end
f(I,structOne.a,structTwo.b) # call
I know how to recursively find all the symbols in an expression, and I can look for the :(.)
to isolate composite values, and I can use @gensym
to make replacement symbol names.
But how can I make the expression a_new[I] = tanh(b_new[I])
which has the same form as the original expression but replaces the composites values with the new symbols?
Do you mean, something like this?
julia> ex = :(structOne.a[I] = tanh(structTwo.b[I]))
:(structOne.a[I] = tanh(structTwo.b[I]))
julia> rep(ex) = ex
rep(ex::Expr) = ex.head == :. ? Symbol(ex.args[2].value, "_new") : ex
rep!(ex) = ex
rep!(ex::Expr) = (ex.args = map(rep, ex.args); foreach(rep!, ex.args); ex)
rep! (generic function with 2 methods)
julia> rep!(ex)
:(a_new[I] = tanh(b_new[I]))
4 Likes
This is my solution, inspired by @uniment’s solution but using “for loop”:
julia> makesym(expr::Expr) = Symbol(expr.args[2].value, "_new")
makesym (generic function with 1 method)
julia> function preprocess!(expr::Expr)
for (i, arg) in enumerate(expr.args)
if arg isa Expr
if arg.head === :(.)
expr.args[i] = makesym(arg)
else
preprocess!(arg)
end
end
end
expr
end
preprocess! (generic function with 1 method)
julia> expr = :(obj1.a[i] = tanh(obj2.b[i]))
:(obj1.a[i] = tanh(obj2.b[i]))
julia> preprocess!(expr)
:(a_new[i] = tanh(b_new[i]))
2 Likes