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
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
MacroTools.jl Expression Walking can iterate expressions.
x, y, z
(from both ex1
and ex2
) and not +,-,^,sum
?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}()