# Macro to automatically create large number of variables

**URL:** <https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150>\
**Category:** General Usage\
**Tags:** macros\
**Created:** [August 10, 2018, 6:52am UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150 "2018-08-10T06:52:28Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![BenjaminBorn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benjaminborn/32/4910_2.png) [@BenjaminBorn](https://discourse.julialang.org/u/BenjaminBorn)\
**Post date:** [August 10, 2018, 6:52am UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/1 "2018-08-10T06:52:28Z")

</div>

Hello everyone,

I have a model where I need to generate a large number of variables of the form

```julia
    r = exp.(Xss[indexes.rSS] .+ X[indexes.r])
    rPrime = exp.(Xss[indexes.rSS] .+ XPrime[indexes.r])
    w = exp.(Xss[indexes.wSS] .+ X[indexes.w])
    wPrime = exp.(Xss[indexes.wSS] .+ XPrime[indexes.w])

```

within a function and and I’d like to use metaprogramming to not have to do this manually.

At the global scope, I can easily do this with `eval()`

```julia
# Preliminary setup
struct index
    r::Int
    w::Int
    rSS::Int
    wSS::Int
end
indexes = index(1,2,1,2)
X = [1.0 2.0]
XSS = [3.0 4.0]
XPrime = [5.0 6.0]
var_names = (:r, :w)

# Create equations
for i in var_names
    varnamePrime = Symbol(i, "Prime")
    varnameSS = Symbol(i, "SS")
    ex = quote
        $i = exp.(XSS[indexes.$varnameSS] + X[indexes.$i])
        $varnamePrime = exp.(XSS[indexes.$varnameSS] + XPrime[indexes.$i])
    end
    eval(ex)
end

```

and it also works with a macro at global scope

```julia
macro gen_equations()
    ex = quote # initialize expression to append to
        temp = 1
    end

    for i in var_names # loop over variables to generate
        varnamePrime = Symbol(i, "Prime")
        varnameSS = Symbol(i, "SS")
        ex_aux = quote
            $i = exp.(XSS[indexes.$varnameSS] + X[indexes.$i])
            $varnamePrime = exp.(XSS[indexes.$varnameSS] + XPrime[indexes.$i])
        end

        append!(ex.args, ex_aux.args) # append to expression
    end

    return esc(ex)
end

@gen_equations

```

However, if I put everything in a function

```julia
function test_scope()
    indexes = index(1,2,1,2)
    X = [1.0 2.0]
    XSS = [3.0 4.0]
    XPrime = [5.0 6.0]
    var_names = (:r, :w)

    @gen_equations
end

```

I get an error that `UndefVarError: var_names not defined`. My guess is that this is a scoping issue. So I defined the same macro but passed all objects explicitly to the macro

```julia
macro gen_equations(var_names, X, XSS, indexes)
    ...
end

```

But if I then try to define my function

```julia
function test_scope()
    indexes = index(1,2,1,2)
    X = [1.0 2.0]
    XSS = [3.0 4.0]
    XPrime = [5.0 6.0]
    var_names = (:r, :w)

    @gen_equations var_names, X, XSS, indexes
end

```

I get a `MethodError: no method matching @gen_equations(::Expr)`.

Any hints would be greatly appreciated. I’m just starting getting my head around macros and I’m still mostly confused.

Setup is Julia 0.6.4 on MacOS.

Thank you very much,

Benjamin

---

<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:** [August 11, 2018, 12:12am UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/2 "2018-08-11T00:12:14Z")

</div>

Can you give more context? Usually when you need a large number of variables, you just want to use an array, e.g.

```julia
r = zeros(100)

```

gives 100 variables called `r[1]` etc.

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [August 11, 2018, 1:03am UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/3 "2018-08-11T01:03:59Z")

</div>

Macros get the _expressions_ of their arguments passed to them. For example given `macro m(x)` and the call `@m 1+2`, inside the macro `x` will equal the expression `:(1+2)`.

Macros run right after code is parsed, so only the expressions are available. The assignment `var_names = ...` in your code will happen at run time, when `test_scope()` is called, which hasn’t happened yet. So in this case a solution would be to call the macro as `@gen_equations r w`, and write it as

```julia
macro gen_equations(var_names...)

```

The key is to distinguish which information is needed at macro-expansion time, and which information is needed at run time. Anything needed at macro-expansion time should be passed to the macro as an argument. Anything used at run time can be picked up from the surrounding scope.

---

<div class="post-metadata">

**Author:** ![BenjaminBorn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benjaminborn/32/4910_2.png) [@BenjaminBorn](https://discourse.julialang.org/u/BenjaminBorn)\
**Post date:** [August 11, 2018, 6:25pm UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/4 "2018-08-11T18:25:35Z")

</div>

Thanks Jeff. That solved it and helped me understand the underlying mechanism much better.

Just a quick follow up. Is there a more elegant way to initialise the expression in the macro to which I append in the loop?

Thanks again, Benjamin

---

<div class="post-metadata">

**Author:** ![BenjaminBorn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benjaminborn/32/4910_2.png) [@BenjaminBorn](https://discourse.julialang.org/u/BenjaminBorn)\
**Post date:** [August 11, 2018, 6:28pm UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/5 "2018-08-11T18:28:27Z")

</div>

Thanks David for your reply. I totally agree that I could also have one array that contains all the variable values. However the model is quite complex and it helps readability of the code to be able to write, e.g., `r` and `rPrime` instead of `r[99]` and `r[100]`.

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [August 12, 2018, 10:06am UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/6 "2018-08-12T10:06:40Z")

</div>

The `temp = 1` is not necessary; you can use just `quote end` or `Expr(:block)`.

---

<div class="post-metadata">

**Author:** ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)\
**Post date:** [August 12, 2018, 4:16pm UTC](https://discourse.julialang.org/t/macro-to-automatically-create-large-number-of-variables/13150/7 "2018-08-12T16:16:45Z")

</div>

I don’t know if you’ve already seen it but [Parameters.jl](https://github.com/mauro3/Parameters.jl) `@unpack` macro (maybe also the `@unpack!_TypeName` macro - see the docs) might help. Similarly, [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) `FieldVector` type might also be useful.
