# Metaprogramming using eval and struct: BUG getting UndefVarError: not defined

**URL:** https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937
**Category:** General Usage
**Tags:** question, bug, eval, struct
**Created:** [April 21, 2020, 12:23am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937 "2020-04-21T00:23:17Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 21, 2020, 12:23am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/1 "2020-04-21T00:23:17Z")

</div>

> I am trying to read parameters from a .csv file for which the name of parameter and its values are given in the .csv file.
> 
> For that I am trying to simply evaluate a simple expression involving putting the value of the parameter in a **struct** , but I get error.  
> I will be delighted if you could provide me a solution to this simple problem?

```julia
# Defining structure
mutable struct PARAM
     θs :: Vector{Float64}
end
θs = zeros(Float64, 1)
hydro = PARAM(θs)

Evaluate =" hydro.θs[1]=0.5"
Evaluate_Parse = Meta.parse(Evaluate)
eval(Evaluate_Parse)

```

. Nevertheless, I get the following error message  
_ERROR: LoadError: UndefVarError: hydro not defined_

---

<div class="post-metadata">

### Author: ![KDr2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdr2/32/2542_2.png) [@KDr2](https://discourse.julialang.org/u/KDr2)
#### Post date: [April 21, 2020, 1:16am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/2 "2020-04-21T01:16:27Z")

</div>

It runs well if just paste your code in REPL, do you have the definition of `hydro` and the execution of `eval` in different modules?

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [April 21, 2020, 1:26am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/3 "2020-04-21T01:26:51Z")

</div>

Why don’t you just use a `Dict` and avoid metaprogramming?

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 21, 2020, 3:25am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/4 "2020-04-21T03:25:31Z")

</div>

There seem to be a bug since you are correct the code works well in REPL but fails in a function.  
Yes I have the definition of hydro and the execution of eval in a different modules

---

<div class="post-metadata">

### Author: ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)
#### Post date: [April 21, 2020, 3:29am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/5 "2020-04-21T03:29:49Z")

</div>

`eval` can only see variables in the global scope, it cannot see local variables.

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 21, 2020, 3:36am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/6 "2020-04-21T03:36:06Z")

</div>

Thanks for shedding light to the problem, how can I make **mutable struct** into **global scope**?

---

<div class="post-metadata">

### Author: ![KDr2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdr2/32/2542_2.png) [@KDr2](https://discourse.julialang.org/u/KDr2)
#### Post date: [April 21, 2020, 4:17am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/7 "2020-04-21T04:17:34Z")

</div>

It’s not about `mutable sutrct PARAM`, it’s about the variable `hydro`.

- `hydro` must be global in some Module
- `eval` must be ensured to evaluate an expression in that Module.

In the code below, `hydro` is a global var in module `T`, and `T.eval` is used to ensure that the parsed expression are evaluated in module `T`.

```julia
julia> module T
       mutable struct PARAM
            θs :: Vector{Float64}
       end
       θs = zeros(Float64, 1)
       hydro = PARAM(θs)
       end
Main.T

julia> Evaluate =" hydro.θs[1]=0.5"
" hydro.θs[1]=0.5"

julia> Evaluate_Parse = Meta.parse(Evaluate)
:(hydro.θs[1] = 0.5)

julia> eval(Evaluate_Parse)
ERROR: UndefVarError: hydro not defined
Stacktrace:
 [1] top-level scope at none:1
 [2] eval at ./boot.jl:331 [inlined]
 [3] eval(::Expr) at ./client.jl:451
 [4] top-level scope at REPL[4]:1

julia> T.eval(Evaluate_Parse)
0.5

julia> T.hydro
Main.T.PARAM([0.5])

julia>

```

---

<div class="post-metadata">

### Author: ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)
#### Post date: [April 21, 2020, 4:48am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/8 "2020-04-21T04:48:24Z")

</div>

Generally it is advisable to avoid using `eval`. From your example I do not see why you need `eval` at all as directly using `hydro.θs[1] = 0.5` without using `eval` would work.

If your use case requires names that you will only know after you load the CSV I would suggest storing the data in either a `Dict` or a `DataFrame` depending on your use case. Both of these allow you to index by name.

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 21, 2020, 8:42pm UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/9 "2020-04-21T20:42:04Z")

</div>

Thanks for your great help and your time. Unfortunately when I introduced your recommendation into the complex program, I was not able to make it work, I am still getting the same error. I think that I would need more clarity on the meaning of **Main.T**?

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [April 21, 2020, 8:52pm UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/10 "2020-04-21T20:52:14Z")

</div>

`T` is just the name of the module that KDr2 is using to hold onto your global variable. All variables you want to change/assign/update/touch with `eval` would need to be globals there — and you need to ensure that you’re explicitly `eval`ing into that module.

But I really think you’ll want to change your angle of attack here — using `eval` like this isn’t very sustainable or maintainable. The other alternatives proposed here will likely make your life much easier. Another option would be a file format like [TOML](https://github.com/JuliaLang/TOML.jl) that can work nicely for what I think you’re trying to do.

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 24, 2020, 9:24am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/11 "2020-04-24T09:24:28Z")

</div>

**PROBLEM RESOLVED 😄**

I want to thank you for inviting me to take a different approach which I solved as follow:

```julia
mutable struct PARAM
     θs :: Vector{Float64}
end

setfield!(hydro, Symbol(θs), Parameter)

```

I get the value of the parameter θs from from a .csv file. This effort is to perform multistep optimisation.

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [April 24, 2020, 2:18pm UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/12 "2020-04-24T14:18:35Z")

</div>

@JosephPollacco Note that this is the same as

`hydro.θs = parameter`

if I understand correctly

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 30, 2020, 2:21am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/13 "2020-04-30T02:21:03Z")

</div>

You are correct that it is the same as:

```julia
hydro.θs = parameter

```

The advantage of

```julia
setfield!(hydro, Symbol("θs"), Parameter)

```

Is that you can perform _Metaprogramming_ by avoiding _eval_. I can now read the symbol directly from a csv file and put it automatically into the structure _hydro_

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [April 30, 2020, 4:01am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/14 "2020-04-30T04:01:37Z")

</div>

But that only works if you have already defined a `struct` with the correct field name beforehand.

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 30, 2020, 4:07am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/15 "2020-04-30T04:07:26Z")

</div>

You are correct, it is the downside of the method. 😞  
If you have a method to create `struct` on the fly that will be great. My challenge is that some parameters are vectors.

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [April 30, 2020, 4:13am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/16 "2020-04-30T04:13:10Z")

</div>

Just use a `Dict`, as was already mentioned several times:

```julia
d = Dict()

d["θs"] = 3
d["hello"] = [4, 5]

```

Of course this will be more efficient if all the values are known to be of a certain type:

```julia
d = Dict{String, Int64}()
d["a"] = 3
d["b"] = -17

```

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [April 30, 2020, 4:14am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/17 "2020-04-30T04:14:18Z")

</div>

Or you can use a `NamedTuple`, which is similar to a struct.  
NamedTupleTools.jl helps with that.

---

<div class="post-metadata">

### Author: ![JosephPollacco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josephpollacco/32/51404_2.png) [@JosephPollacco](https://discourse.julialang.org/u/JosephPollacco)
#### Post date: [April 30, 2020, 4:21am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/18 "2020-04-30T04:21:40Z")

</div>

**Thanks for the suggestion of using Dict**

My understanding is that one of the limitation of _Dict_ is that one cannot use Vectors. “θs” is a parameter describing the maximum saturated soil moisture of a layer in a soil. I have many soil layers, so my understanding is that _Dict_ might not be the best solution for using Vectors, but I might be wrong. For e.g. this may not be possible:

```julia
d["θs[1]"] = 1
d["θs[2]"] = 2

```

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [April 30, 2020, 4:28am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/19 "2020-04-30T04:28:10Z")

</div>

Just do `d["θs"]=[1,2]`, ie store the vector as the value.

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [April 30, 2020, 4:32am UTC](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937/20 "2020-04-30T04:32:17Z")

</div>

Did you actually try to run that code? It works fine.

```julia

> d["θs[1]"] = 1
1

> d["θs[2]"] = 2
2

> d
Dict{Any,Any} with 2 entries:
  "θs[2]" => 2
  "θs[1]" => 1

```

But that’s not what you really want (probably).

I think you want

```julia

> d = Dict()
Dict{Any,Any} with 0 entries

> d["θs"] = [3, 4, 5]
3-element Array{Int64,1}:
 3
 4
 5

> d["θs"][1]
3

> d["θs"][2]
4

```

`d["θs"]` is now a `Vector` whose elements you can extract in the usual way.

[Next page](https://discourse.julialang.org/t/metaprogramming-using-eval-and-struct-bug-getting-undefvarerror-not-defined/37937.md?page=2)
