# Problem evaluating symbol for macro inside function

**URL:** https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142
**Category:** General Usage
**Tags:** macros
**Created:** [October 21, 2019, 6:17pm UTC](https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142 "2019-10-21T18:17:01Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![iloaiza](https://avatars.discourse-cdn.com/v4/letter/i/8c91f0/32.png) [@iloaiza](https://discourse.julialang.org/u/iloaiza)
#### Post date: [October 21, 2019, 6:17pm UTC](https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142/1 "2019-10-21T18:17:02Z")

</div>

Hey! I have been trying to make a saving macro to simplify my life and skip having to do the full saving syntax while keeping track of what I’m saving where. To do this, I have started writing a module. The main macro is as follows:

```julia
macro saving(funcname::String,params...)
	quote
		oldfile($funcname)
		h5write($funcname*".h5","paramsNames",stringSymbolSeparator($params))
		for (n,name) in enumerate(stringSymbolSeparator($params))
			h5write($funcname*".h5",name,eval($(esc(params))[n]))
			println("Saved $($(params)[n])")	
		end
	end
end

```

Where the oldfile function just makes sure that there isn’t any file saved with funcname (and moves it to a .old file if it exists), and stringSymbolSeparator takes “params” as symbols and returns an array where each entry is the text used to write the variables (so that if I run `@saving "test" var1`, it will save the variable var1 in “test.h5” HDF5 file under the name of “var1”). When I try running the macro with variables that I have saved in the global scope it seems to work fine, my problem is that if I run the macro inside of a function, the eval command seems to be evaluating within the wrong scope and I get an UndefVarError. I’m pretty sure that the workaround has something to do with the macro hygiene, but after looking for a while I just can’t seem to fix it.  
Thanks a lot for your help 🙂

---

<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: [October 21, 2019, 9:13pm UTC](https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142/2 "2019-10-21T21:13:17Z")

</div>

Using `eval()` inside a macro is almost never necessary, and it’s almost always a signal that something has gone wrong. In this case, there’s no need for `eval` at all.

Rather than tackling the full version of your code, here’s a simple example of saving a single variable. First, I defined a stub `h5write` function so I don’t actually have to generate hdf files for testing:

```julia
julia> function h5write(filename, data, label)
         println("saving: $data with label $label in file $filename")
       end
h5write (generic function with 1 method)

```

Then I built a macro to call that function. Note the use of `esc(param)` to get the un-escaped variable in the expanded code, and the use of `QuoteNode` to turn a variable into a symbol giving the _name_ of that variable:

```julia
julia> macro saving(name, param)
         quote
           h5write(string($name, ".h5"), $(esc(param)), string($(QuoteNode(param))))
         end
       end
@saving (macro with 1 method)

```

We can verify that this works at local scope:

```julia
julia> let 
         local_var = [1, 2, 3]
         @saving "test" local_var
       end
saving: [1, 2, 3] with label local_var in file test.h5

```

and global scope:

```julia
julia> global_var = [1, 2]
2-element Array{Int64,1}:
 1
 2

julia> @saving "test" global_var
saving: [1, 2] with label global_var in file test.h5

```

---

<div class="post-metadata">

### Author: ![iloaiza](https://avatars.discourse-cdn.com/v4/letter/i/8c91f0/32.png) [@iloaiza](https://discourse.julialang.org/u/iloaiza)
#### Post date: [October 24, 2019, 4:56pm UTC](https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142/3 "2019-10-24T16:56:55Z")

</div>

Perfect, thanks this helps a lot.  
I still had some problems for implementing a for loop inside the macro to run over a variable number of parameters. In the end I ended just doing one part in a macro, and another part in a function and I have to write two lines instead of one. Still, it works like it should now.  
Thanks again!

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [February 11, 2020, 2:00pm UTC](https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142/4 "2020-02-11T14:00:49Z")

</div>

Sorry to resurrect, but how would one deal with a loop?

If I wanted to iterate over a collection of variables I’d use something like this:

```julia
for obj in (obj1, obj2, obj3)
    @saving "filename" obj
end

```

but then all my “labels” would be `obj` instead of `obj1`, `obj2`, and `obj3`.

MWE:

```julia
julia> obj1 = rand(2);

julia> obj2 = "123";

julia> obj3 = b"456";

julia> for obj in (obj1, obj2, obj3)
           @saving "filename" obj
       end
saving: [0.6583616079535075, 0.02077698131163519] with label obj in file filename.h5
saving: 123 with label obj in file filename.h5
saving: UInt8[0x34, 0x35, 0x36] with label obj in file filename.h5

```

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [February 11, 2020, 2:37pm UTC](https://discourse.julialang.org/t/problem-evaluating-symbol-for-macro-inside-function/30142/5 "2020-02-11T14:37:18Z")

</div>

Never mind, I found out about `Base.@locals`, which solved this nicely!

> [@Using Symbol within function (unexpected behaviour)](https://discourse.julialang.org/t/using-symbol-within-function-unexpected-behaviour/24029/2):
>
> eval() always operates in global scope. Check out the help text: help?\> eval ... eval(expr) Evaluate an expression in the global scope of the containing module. ... Since eval() operates in global scope, it does not have access to the values of your local variables. Since Julia 1.1, though, we have the Base.@locals() macro, which gives you a dictionary mapping local variable names to their local values. Your use case might be a good fit for that: julia\> function foo() a = 1 …
