Is there a simple and type stable way to do this?

```
julia> f(:(x^2+sum(x,y-3,z)))
4-element Array{Symbol,1}:
:x
:x
:y
:z
```

Is there a simple and type stable way to do this?

```
julia> f(:(x^2+sum(x,y-3,z)))
4-element Array{Symbol,1}:
:x
:x
:y
:z
```

1 Like

It’s pretty easy to walk expression trees, typing `:(x^2+1) |> dump`

etc. will let you see how they are structured. Here’s a rough solution, but there are expressions which will trip this up:

```
julia> walk!(list) = ex -> begin
ex isa Symbol && push!(list, ex)
ex isa Expr && ex.head == :call && map(walk!(list), ex.args[2:end])
list
end
walk! (generic function with 1 method)
julia> :(x^2+sum(x,y-3,z)) |> walk!([])
4-element Array{Any,1}:
:x
:x
:y
:z
```

1 Like

MacroTools.jl Expression Walking can iterate expressions.

- How to get just
`x, y, z`

(from both`ex1`

and`ex2`

) and not`+,-,^,sum`

? - How to return the list directly from postwalk instead of pushing to external list?

```
import MacroTools: postwalk
function get_ex_symbols1(ex)
list = []
postwalk(x -> x isa Symbol ? (push!(list, x); x) : x, ex)
return Set{Symbol}(list)
end
function get_ex_symbols2(ex)
list = []
walk!(list) = ex -> begin
ex isa Symbol && push!(list, ex)
ex isa Expr && ex.head == :call && map(walk!(list), ex.args[2:end])
list
end
Set{Symbol}(walk!([])(ex))
end
ex1 = :(x^2+sum(x,y-3,z))
ex2 = :(function f(x,y); x=x+1; y=y^2; z=sum(x,y) end);
```

```
julia> get_ex_symbols1(ex1)
Set{Symbol} with 7 elements:
:+
:^
:y
:-
:z
:sum
:x
julia> get_ex_symbols1(ex2)
Set{Symbol} with 7 elements:
:+
:z
:f
:^
:y
:sum
:x
julia> get_ex_symbols2(ex1)
Set{Symbol} with 3 elements:
:y
:z
:x
julia> get_ex_symbols2(ex2)
Set{Symbol}()
```

1 Like