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]))
```

1 Like