# Macro cannot see variables in calling function's scope

**URL:** <https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806>\
**Category:** General Usage\
**Created:** [February 18, 2020, 11:53am UTC](https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806 "2020-02-18T11:53:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![brownlight](https://avatars.discourse-cdn.com/v4/letter/b/9d8465/32.png) [@brownlight](https://discourse.julialang.org/u/brownlight)\
**Post date:** [February 18, 2020, 11:53am UTC](https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806/1 "2020-02-18T11:53:05Z")

</div>

Scenario:  
A variable exists in the (local) scope of a function. func1 calls macro passing it the variable as a parameter. But, the macro can’t see the variable. I have run into this issue when migrating code from version 0.4.6 to 1.3.0.  
The example code below works in 0.4.6. How can I get back the intended behavior in 1.3.0?

Example:  
Essentially, a macro and a function are defined in a file D:\test.jl as below:

```julia
macro remove(array, index) 
     quote
       temp = getindex($array, $index) 
       setindex!($array, 0, $index) 
       temp     
     end 
end

function func1(matrix)
	# do something with the matrix
	location = 5
	removed_value = @remove matrix location
	println(matrix)
	removed_value
end

```

Now on the REPL (Julia 1.3.1), func1() is called:

```julia
julia> include("d:\\test.jl")
func1 (generic function with 1 method)

julia> B=rand(3,3)
3x3 Array{Float64,2}:
 0.672525 0.185575 0.519812
 0.0657534 0.824389 0.997873
 0.298938 0.879692 0.544854

julia> func1(B)
ERROR: UndefVarError: matrix not defined
Stacktrace:
 [1] func1(::Array{Float64,2}) at D:\test.jl:3
 [2] top-level scope at REPL[6]:1

```

However, the same code works, as intended, on Julia 0.4.6:

```julia
julia> include("d:\\test.jl")
func1 (generic function with 1 method)

julia> B=rand(3,3)
3x3 Array{Float64,2}:
 0.31986 0.0326584 0.459205
 0.0532861 0.613278 0.954343
 0.889699 0.195983 0.969102

julia> func1(B)
[0.3198596980916635 0.03265841972646388 0.45920484654949445
 0.05328610654424648 0.0 0.9543434785771836
 0.8896992715733547 0.19598268732691326 0.9691021279154293]
0.6132781328188774

```

Having read Julia’s docs on “Scope of Variables” and posts on changes in Scope behavior from version 1.0 … I am still unable to figure out what I am doing wrong.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [February 18, 2020, 12:06pm UTC](https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806/2 "2020-02-18T12:06:11Z")

</div>

You are missing the `esc` function.

```julia
julia> @macroexpand @remove matrix location
quote
    #= REPL[52]:3 =#
    var"#9#temp" = Main.getindex(Main.matrix, Main.location)
    #= REPL[52]:4 =#
    Main.setindex!(Main.matrix, 0, Main.location)
    #= REPL[52]:5 =#
    var"#9#temp"
end

julia> macro remove2(array, index) 
            esc(quote
              temp = getindex($array, $index) 
              setindex!($array, 0, $index) 
              temp     
            end)
       end
@remove2 (macro with 1 method)

julia> @macroexpand @remove2 matrix location
quote
    #= REPL[57]:3 =#
    temp = getindex(matrix, location)
    #= REPL[57]:4 =#
    setindex!(matrix, 0, location)
    #= REPL[57]:5 =#
    temp
end

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [February 18, 2020, 3:47pm UTC](https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806/3 "2020-02-18T15:47:34Z")

</div>

The relevant part of the docs is [Macro Hygiene](https://docs.julialang.org/en/v1/manual/metaprogramming/#Hygiene-1).

---

<div class="post-metadata">

**Author:** ![brownlight](https://avatars.discourse-cdn.com/v4/letter/b/9d8465/32.png) [@brownlight](https://discourse.julialang.org/u/brownlight)\
**Post date:** [February 18, 2020, 6:33pm UTC](https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806/4 "2020-02-18T18:33:25Z")

</div>

@GunnarFarneback: Thank you! It works now.

@Sukera: That portion of the docs appears to be written well and to-the-point for an intermediate user. I feel that working of the powerful Metaprogramming features will become accessible to a wider audience as the docs refine with time.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [February 18, 2020, 7:00pm UTC](https://discourse.julialang.org/t/macro-cannot-see-variables-in-calling-functions-scope/34806/5 "2020-02-18T19:00:38Z")

</div>

Metaprogramming really should only be used if it’s absolutely necessary and by someone more familiar with the language than a beginner. It’s a powerful technique, but because of that it takes some skill to judge when it’s the right tool for the job.
