# Replace symbols within an expression

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.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

Perfect example. Thanks!

This is my solution, inspired by @uniment’s solution but using “for loop”:

``````julia> makesym(expr::Expr) = Symbol(expr.args.value, "_new")
makesym (generic function with 1 method)

julia> function preprocess!(expr::Expr)
for (i, arg) in enumerate(expr.args)
if arg isa Expr
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]))
``````
1 Like