# Esc() in macro definitions in meta programming

**URL:** https://discourse.julialang.org/t/esc-in-macro-definitions-in-meta-programming/11885
**Category:** New to Julia
**Created:** [June 22, 2018, 5:15pm UTC](https://discourse.julialang.org/t/esc-in-macro-definitions-in-meta-programming/11885 "2018-06-22T17:15:12Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![cuchxq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cuchxq/32/3830_2.png) [@cuchxq](https://discourse.julialang.org/u/cuchxq)
#### Post date: [June 22, 2018, 5:15pm UTC](https://discourse.julialang.org/t/esc-in-macro-definitions-in-meta-programming/11885/1 "2018-06-22T17:15:12Z")

</div>

Hi, I am not sure if this is the right place for meta programming questions. Please redirect me if you think there is a better place to ask this question.

I am trying to understand the use of `$(esc())` in macro definitions. I read the following source to learn about it.  
[Source1](https://en.wikibooks.org/wiki/Introducing_Julia/Metaprogramming),  
[Source2](https://docs.julialang.org/en/v0.6.1/manual/metaprogramming/).

My understanding is that in order to keep macro hygiene, I need to use `esc` to keep global space variables seperate from local variables.  
So I wrote the following macro, and expanded it to see the result.

```julia
Julia> n = 1
Julia> 
macro esc_example(a)
    quote 
        n = 3
        println(n)
        println($n)
        println($(esc(n)))

        println($a)
        println($(esc(a)))
    end
end

Julia> @esc_example(n)
3
1
1
3
1

Julia> macroexpand(:(@esc_example(n)))
quote # REPL[48], line 3:
    #33#n = 3 # REPL[48], line 4:
    (Main.println)(#33#n) # REPL[48], line 5:
    (Main.println)(1) # REPL[48], line 6:
    (Main.println)(1) # REPL[48], line 8:

    (Main.println)(#43#n) # REPL[56], line 9:
    (Main.println)(n)
end

```

I defined `n` as 1 in REPL, and a local variable `n` as 3.  
I am not sure if esc() can be used on macro arguments, so I want to test it as well.

Let me go through it line by line, left side is the macro definition, and right side is the macro expansion .

1. `n = 3` =\> `#33#n = 3 # REPL[48], line 4:`  
`n` is defined locally as 3, so when expanding macro, the name is reassigned with a name `#33#n` to make sure it does not collide with names in global space. I think this one is straight forward.

2. `println(n)` =\> `(Main.println)(#33#n) # REPL[48], line 5:`  
Just prints out the local `n` value, understood.

3. `println($n)` =\> `(Main.println)(1) # REPL[48], line 6: `  
`$n` is string interpolation. Replacing `n` in global space with its value 1.  
This one is a little confusing because I thought I have to use $(esc(n)) to get the value of n in global space.

4. `println($(esc(n)))` =\> `(Main.println)(1) # REPL[48], line 8: `  
This is the use of esc(). and it is getting the value of `n` from global space. Understood. But I thought the macro expansion will replace it with something like `Main.n`, rather than the value 1, because it should not be evaluated at macro expand time. Am I right? And if they have the same effect, what is the benefit of using `esc()`?

5. `println($a)` =\> `(Main.println)(#43#n) # REPL[56], line 9:`  
I think this line is a bug. Because this line should prints out the value of `a`, which is `n` in global space, the value 1. But instead it is replaced with the local `n`.

6. `println($(esc(a)))` =\> `(Main.println)(n) `  
Like I said in the before, I don’t know if `esc()` can be used on arguments so I am trying it out.  
I was expecting an error, but it was replaced with `n` in global space. Maybe someone can help me understand this part.

Here is the version info from Julia

```julia
julia> versioninfo()
Julia Version 0.6.3
Commit d55cadc350 (2018-05-28 20:20 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin14.5.0)
  CPU: Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, skylake)

```

I apologize for the long post. I am trying my best to explain my confusion.  
And thank you for reading through my question.

---

<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: [June 22, 2018, 5:52pm UTC](https://discourse.julialang.org/t/esc-in-macro-definitions-in-meta-programming/11885/2 "2018-06-22T17:52:12Z")

</div>

You’ve mixed up interpolating and escaping a bit in your example. When you do `$n`, you are splicing the current _value_ of `n` (in this case, the value in the global scope) into the resulting expression. Escaping this _value_ does nothing. You’ve essentially hard-coded that `1` into the resulting expression.

`esc()` is applied to an expression or a symbol to cause that symbol to be resolved in the caller’s scope, not the macro definition’s scope. For example:

```julia
julia> macro set_n()
         quote
           $(esc(:n)) = 1
         end
       end
@set_n (macro with 1 method)

julia> @macroexpand @set_n()
quote # REPL[13], line 3:
    n = 1
end

julia> n
ERROR: UndefVarError: n not defined

julia> @set_n()
1

julia> n
1

```

---

<div class="post-metadata">

### Author: ![cuchxq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cuchxq/32/3830_2.png) [@cuchxq](https://discourse.julialang.org/u/cuchxq)
#### Post date: [June 22, 2018, 6:52pm UTC](https://discourse.julialang.org/t/esc-in-macro-definitions-in-meta-programming/11885/3 "2018-06-22T18:52:51Z")

</div>

Ah, I see. That makes sense now. I missed the part that `esc()` takes an expression. Thank you very much.

But do you think bullet 5 ( the line starts with `println($a)` ) is a bug? Because I think when using `$a`, it should be expanded to `n` in global space, but in this case, it was expanded to local n.
