# Forwarding a macro that returns a variable?

**URL:** https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508
**Category:** Optimization (Mathematical)
**Tags:** question, jump
**Created:** [February 3, 2025, 9:14pm UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508 "2025-02-03T21:14:10Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![brunompacheco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brunompacheco/32/209375_2.png) [@brunompacheco](https://discourse.julialang.org/u/brunompacheco)
#### Post date: [February 3, 2025, 9:14pm UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508/1 "2025-02-03T21:14:10Z")

</div>

I am trying to forward the [@variable](https://jump.dev/JuMP.jl/stable/api/JuMP/#@variable) macro from JuMP, so that instead of passing a model to it, I pass my custom struct that has a model as a field. I was able to do it when the new macro is declared locally:

```julia
using JuMP

struct Player
    model::Model
end

macro pvar(player, args...) # forwards JuMP.@variable to Player.model
    return :(JuMP.@variable($(esc(player)).model, $(args...)))
end

p = Player(Model())

@pvar(p, y >= 1) # works!

```

However, as soon as I move the code to my module, it breaks. I believe my problem is in trying to return a local variable (the one created inside JuMP.@variable). MWE:

```julia
using JuMP

module MyModule
    using JuMP

    struct Player
        model::Model
    end

    macro pvar(player, args...) # forwards JuMP.@variable to Player.model
        return :(JuMP.@variable($(esc(player)).model, $(args...)))
    end
end

p = MyModule.Player(Model())

MyModule.@pvar(p, y >= 1) # fails :(

```

The error is:

```julia
ERROR: LoadError: Global MyModule.y does not exist and cannot be assigned. Declare it using `global` before attempting assignment.

```

I tried prepending a `global` to the inner macro call and escaping the whole thing. I am really new to using macros and I have a hard time understanding the order of interpolations and executions.

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [February 3, 2025, 9:33pm UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508/2 "2025-02-03T21:33:15Z")

</div>

Hi @brunompacheco,

Before telling you how to do this, why do you want to do this? What is the higher-level goal you are trying to achieve?

I would strongly encourage you _not_ to define new macros. As you have seen, they can be tricky to get correct. Is there some other way that you can achieve what you are trying to do?

You may want to take a read of [Extensions · JuMP](https://jump.dev/JuMP.jl/stable/developers/extensions/)

---

<div class="post-metadata">

### Author: ![brunompacheco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brunompacheco/32/209375_2.png) [@brunompacheco](https://discourse.julialang.org/u/brunompacheco)
#### Post date: [February 3, 2025, 11:31pm UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508/3 "2025-02-03T23:31:57Z")

</div>

Hi @odow,

Each Player has a feasible space and an objective function, but I will manipulate the objective function (change parameters, explore separability), so I think I cannot just define it as a Model. At first, I thought about extending Model, but I got discouraged by [Defining new JuMP models](https://jump.dev/JuMP.jl/stable/developers/extensions/#Defining-new-JuMP-models). So now, my idea is to have a Model as a field of Player, and forward the `@variable` and `@constraint` macros, so that the user can easily define the feasible space. As an alternative, I thought about forwarding `add_variable` and `add_constraint`, but that is also discouraged.

My last resort is for the user to build a Model with the feasible region and pass that when declaring the Player. But I would then make a deepcopy of the model to avoid counterintuitive interferences with the algorithm.

Feel free to let me know what you think of it. Your suggestions are highly appreciated.

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [February 3, 2025, 11:57pm UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508/4 "2025-02-03T23:57:37Z")

</div>

What is your ideal syntax for the smallest example? In other words, what would be the first example in the README or documentation?

---

<div class="post-metadata">

### Author: ![brunompacheco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brunompacheco/32/209375_2.png) [@brunompacheco](https://discourse.julialang.org/u/brunompacheco)
#### Post date: [February 4, 2025, 12:08am UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508/5 "2025-02-04T00:08:25Z")

</div>

Probably something in the lines of

```julia
p1 = Player(QuadraticPayoff(0, [2, 1]))
@add_variable(p1, x1 >= 0)

p2 = Player(QuadraticPayoff(0, [1, 2]))
@add_variable(p2, x2 >= 0)

P = [p1, p2]

x_init = find_feasible(P)

x_opt = solve(P)

```

For context, `QuadraticPayoff` is used in `solve` both by itself and to define the (parameterized) objective of the Model.

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [February 4, 2025, 12:19am UTC](https://discourse.julialang.org/t/forwarding-a-macro-that-returns-a-variable/125508/6 "2025-02-04T00:19:42Z")

</div>

Just make the syntax:

```julia
p1 = Player(QuadraticPayoff(0, [2, 1]))
@variable(p1.model, x1 >= 0)

p2 = Player(QuadraticPayoff(0, [1, 2]))
@variable(p2.model, x2 >= 0)
P = [p1, p2]
x_init = find_feasible(P)
x_opt = solve(P)

```

Defining a new macro is should be a last resort. JuMP uses macros so that we can intercept `x >= 0` as bound and constraints instead of comparisons, and so we can build linear expressions more efficiently.

If you tell people “just write `p.model`, then you can use all of JuMP” it is much simpler than opting into a subset of the JuMP features or defining new macros.
