Dynamically Naming Expressions and Constraints in JuMP

In JuMP, it appears that expressions, constraints, and variables cannot be dynamically named using string interpolation (i.e., the $ symbol) directly within the identifiers of the @variable or @expression macros. Given this limitation, I am curious about the best approach to dynamically generate names for expressions and constraints within a loop.

Currently, my workaround involves defining an empty dictionary outside the loop, which is then populated with expressions and constraints as follows:

exp = Dict()
for s in 1:S
    exp[s] = @expression(model, sum(a[i] * x[i] for i in 1:n))
    # Additional code follows
end

Is this approach considered the recommended practice for naming expressions and constraints dynamically?

Currently, my workaround involves defining an empty dictionary outside the loop, which is then populated with expressions and constraints as follows:

Yes, this is a good approach.

JuMP variables and expressions are just regular Julia types. They are not special. The JuMP macros provide some convenient constructors, like @expression(model, exp[s in 1:S], ...), but you don’t need to use them. Use whatever data structures are most convenient for your problem.

See also, parts of the docs like this Variables · JuMP, or tutorials like The network multi-commodity flow problem · JuMP.