# Determine the scope of symbols in an Expr

**URL:** <https://discourse.julialang.org/t/determine-the-scope-of-symbols-in-an-expr/47993>\
**Category:** General Usage\
**Tags:** metaprogramming, scope\
**Created:** [October 8, 2020, 5:17pm UTC](https://discourse.julialang.org/t/determine-the-scope-of-symbols-in-an-expr/47993 "2020-10-08T17:17:11Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 8, 2020, 5:17pm UTC](https://discourse.julialang.org/t/determine-the-scope-of-symbols-in-an-expr/47993/1 "2020-10-08T17:17:11Z")

</div>

I asked about this [on Zulip](https://julialang.zulipchat.com/#narrow/stream/225542-helpdesk/topic/running.20name.20resolution.20within.20a.20macro) and cleaned it up and [posted to Stack Overflow](https://stackoverflow.com/questions/64252864/how-can-i-resolve-the-scope-of-variables-in-a-julia-expression/64252865#64252865) but I figure it might be helpful to cross pollinate here as well. I know I’ve wondered how to do this a few times, so probably other people have too.

Here’s the question:

Is there any way to run name resolution on an arbitrary expression without running it? e.g. I would like to take an expression such as

```julia
quote
    x = 1
    y = 2*x + 1
    z = x^2 - 1
    f(x) = 2*x + 1
end

```

and be told that the names defined in the scope of this block are `x, y, z, f` and the names `*, +, ^, -` are pulled in from outside the scope of this block. Bonus points if it can tell me that there’s a sub-scope defined in the body of `f` which creates it’s own name `x` and pulls in `+` from an enclosing scope.

This question appeared in the [Julia Zulip community](https://julialang.zulipchat.com/#narrow/stream/225542-helpdesk/topic/running.20name.20resolution.20within.20a.20macro/near/212615562)

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 8, 2020, 5:17pm UTC](https://discourse.julialang.org/t/determine-the-scope-of-symbols-in-an-expr/47993/2 "2020-10-08T17:17:48Z")

</div>

And the answer:

Thanks to @tkf for [showing me how to solve this on Zulip](https://julialang.zulipchat.com/#narrow/stream/225542-helpdesk/topic/running.20name.20resolution.20within.20a.20macro)

We can get a list of locally defined names in the outermost scope of a julia expression like so:

```julia
ex = quote
    x = 1
    y = 2*x + 1
    z = x^2 - 1
    f(x) = 2*x + 1
end

```

```julia
using JuliaVariables, MLStyle

function get_locals(ex::Expr)
    vars = (solve_from_local ∘ simplify_ex)(ex).args[1].bounds
    map(x -> x.name, vars)
end

julia> get_locals(ex)
 4-element Array{Symbol,1}:
  :f
  :y
  :z
  :x

```

and we can get the symbols pulled in from _outside_ the scope like this:

```julia
_get_outers(_) = Symbol[]
_get_outers(x::Var) = x.is_global ? [x.name] : Symbol[]
function _get_outers(ex::Expr)
    @match ex begin
        Expr(:(=), _, rhs) => _get_outers(rhs)
        Expr(:tuple, _..., Expr(:(=), _, rhs)) => _get_outers(rhs)
        Expr(_, args...) => mapreduce(_get_outers, vcat, args)
    end
end

get_outers(ex) = (unique! ∘ _get_outers ∘ solve_from_local ∘ simplify_ex)(ex)

julia> get_outers(ex)
 6-element Array{Symbol,1}:
  :+
  :*
  :-
  :^

```
