I’m working to update a module compatible with JuMP v1.1.1 to the newest version of JuMP. Within the module is code similar to:
m = esc(m)
x = esc(F)
:(@NLconstraint( $(m), $(x) <= 4) )
end # module HoldBug
m = Model()
In the newest version of JuMP I get
UndefVarError: x not defined.
Expanding the macro reveals the issue, in JuMP1.4 the variable x is being held by HoldBug
var"#4###315" = JuMP.Expr(:escape, Main.HoldBug.x)
In JuMP1.1, it looks like this
JuMP._parse_NL_expr_runtime(m, x, var"#5#tape", var"#7###315", var"#6#values")
Does anybody have advice on how to work around this?
Writing macros that call macros is very difficult to get correct. You need to properly escape things.
julia> module HoldBug
macro mytest(m, F)
return esc(:(@NLconstraint($m, $F <= 4)))
end # module HoldBug
WARNING: replacing module HoldBug.
julia> using .HoldBug
julia> using JuMP
julia> m = Model();
julia> @variable(m, x);
julia> @macroexpand HoldBug.@mytest(m, x)
#= REPL:4 =#
#= /Users/oscar/.julia/dev/JuMP/src/macros.jl:2383 =#
#= /Users/oscar/.julia/dev/JuMP/src/macros.jl:2384 =#
#= /Users/oscar/.julia/dev/JuMP/src/macros.jl:2377 =#
#= /Users/oscar/.julia/dev/JuMP/src/macros.jl:1846 =#
var"#73###323" = JuMP.Expr(:call, :<=, x, 4)
#= /Users/oscar/.julia/dev/JuMP/src/macros.jl:2378 =#
julia> HoldBug.@mytest(m, x)
x - 4.0 ≤ 0
What are you trying to achieve? You should consider instead the raw expression input: Nonlinear Modeling · JuMP
I’m updating the Complementarity package, this piece of code is from the MPEC portion of the module.
Right now the package recursively escapes the expression F, so for example if F = 3*x-y then inside of the macro you get something like
3*esc(x) - esc(y)
I’ll experiment with add_nonlinear_constraint, but I’ve tried this in the past and it seems to be a similar issue, where the module hangs onto the variable.
Thanks for taking a look at it
Ah. This is pretty non-trivial. We changed quite a lot. The complementarity package is also really old. It’s almost worth using it as inspiration for a rewrite, rather than trying to minimally modify the code.
Good to know. This is actually the last piece to have the code, at least, run. It’s also a good exercise to learn more Julia.
Thanks again for the advice.