# Macro: escaping, evaluation, scope etc,

**URL:** <https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875>\
**Category:** General Usage\
**Tags:** macros\
**Created:** [February 5, 2022, 8:57pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875 "2022-02-05T20:57:06Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [February 5, 2022, 8:57pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/1 "2022-02-05T20:57:06Z")

</div>

Playing around with macros.

```julia
macro gk(x)
    ks = keys(eval(x))
    return ks
end

p = (a=1, b="b")

julia> @gk p
(:a, :b)

```

That’s OK, that’s what I want. Now, if the macro is defined inside a separate module, I couldn’t find any way to achieve te same result. No escape ☹

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [February 5, 2022, 9:16pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/2 "2022-02-05T21:16:18Z")

</div>

> [@Eben60](#):
>
> `eval(x)`

It’s almost never necessary or helpful to use `eval` in a macro. A macro takes _code_ (not the values represented by that code) and produces new code, so it shouldn’t need to `eval` anything.

It seems like you don’t need a macro at all–using a function solves the problem perfectly:

```julia
function gk(x)
  keys(x)
end

```

(or, at that point, don’t even define `gk` at all and just call `keys` yourself).

Can you explain more about the problem you actually want to solve?

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [February 5, 2022, 9:31pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/3 "2022-02-05T21:31:19Z")

</div>

```julia
macro unp(x)

    local nt = @eval $x
    for k in keys(nt)
        local v = nt[k]
        @eval $k = $v
    end
end
p = (a=1, b="b")

julia> @unp p

julia> a
1

julia> b
"b"

```

Unpack a NamedTuple and create new variables in the calling scope. I know, that’s unsafe, and it is not that I actually need it, but I’m curious how can that be done. In the example above it works. How can that be done if the macro called in a different scope?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [February 5, 2022, 9:59pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/4 "2022-02-05T21:59:35Z")

</div>

No, that’s not possible in general. The way Julia works, all (local) variables need to be resolved statically.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [February 5, 2022, 11:53pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/5 "2022-02-05T23:53:29Z")

</div>

Yes, indeed, I don’t need a macro here, just function:

```julia
function unp(x)
    exs = [Expr(:(=), k, QuoteNode(x[k])) for k in keys(x)]
    eval.(exs)
end

p = (a=1, b="b")

julia> a
ERROR: UndefVarError: a not defined
 
julia> unp(p);

julia> a
1

julia> b
"b"

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [February 6, 2022, 3:32pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/6 "2022-02-06T15:32:24Z")

</div>

No, we mean that `eval` always evaluate on `global` scope, and therefore your function will always create `global` variables. If you call it inside a function it will not create variables `local` to the function, and if the function had any local variables of the same name they will be shadowing such global variables. What you see only work because you are working in `global` scope in the REPL.

```julia
julia> function unp(x)
           exs = [Expr(:(=), k, QuoteNode(x[k])) for k in keys(x)]
           eval.(exs)
       end
unp (generic function with 1 method)

julia> function test_unp(p)
           a = 10
           b = "c"
           unp(p)
           @show a
           @show b
           return
       end
test_unp (generic function with 1 method)

julia> test_unp((a=1, b="b"))
a = 10
b = "c"

julia> a
1

julia> b
"b"

```

Here you can see that the variables are global (appeared out of the function that called `unp`) and that the `local` variables shadowed them inside the function.

If we do **not** define a local `a` and a local `b` inside the `test_unp` function, then the function see the global variables, but I am not sure this works outside of the REPL. Julia has something called “Age of the world” that sometimes prevents things just evaluated to be used immediately in the sequence.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 6, 2022, 3:37pm UTC](https://discourse.julialang.org/t/macro-escaping-evaluation-scope-etc/75875/7 "2022-02-06T15:37:42Z")

</div>

OP everyone in this thread is correct, you should not be using `eval` ever. It is not though it works with expressions, in Julia using “metaprogramming” refers to re-writing expressions in local scope.

You may be interested in the following packages

- [StaticModules.jl](https://github.com/MasonProtter/StaticModules.jl) which provides the macro `@with` for working with objects.
- [UnPack.jl](https://github.com/mauro3/UnPack.jl) which allows easy unpacking of objects
- [DataFramesMeta.jl](https://github.com/JuliaData/DataFramesMeta.jl) for doing a similar unpacking as StaticModules.jl but with extra performance benefits designed for DataFrames
- [AddToField.jl](https://github.com/pdeffebach/AddToField.jl) which allows for packing objects into dictionaries or named tuples easily.
