Obviously it does not work. Is there a workaround that would make it feasible to declare constant globals from function?
I want to have some sort of ‘function’ that I would later save with JLD2 so I could reload the parameters later on. If there’s some other way I could do it let me know.
Or is there some other way?
function test()
"Definition of x1"
const global x1 = 1
"Definition of x2"
const global x2 = 1
# many more
"Definition of xk_1"
const global xk_1 = 1
"Definition of xk"
const global xk = 1
end
What you propose is quite inefficient from perspective of a user
The way you should do this is with a NamedTuple or struct (mutable or otherwise) or, if you really need the ability to add or remove constants, a global constant Dict.
TLDR: if your constants aren’t really constant, don’t tell julia they are.
It is not only less tidy, it is also not nearly as flexible, and can also be dangerous if it isn’t understood properly. People sometimes assume you can just do :
const a = 10
# define some functions that "capture" `a` and run them
# later I want to change a and rerun my code, so I run:
a = 11
# rerun my functions from before
But you can’t. If the value of a was captured in any functions that have now been compiled, changing a without also redefining those functions will lead to the wrong result. This is why the following warning is issued at the REPL when you do this:
WARNING: redefinition of constant a. This may fail, cause incorrect answers, or produce other errors.
Basically, global constants should be treated as global constants, and the fact that julia lets you change them (as long as their type doesn’t change) can be misleading if you don’t understand that.
So in that case, if you take care to follow the rules (which is already a hassle), you’re subjecting yourself to a lot of unnecessary redefinition and recompilation. So if the constants aren’t literally meant to be constant, put them into something mutable or temporary.
You will see this same advice issued pretty often on here, as this is a common question
There’s nothing wrong with this at all! It could be convenient to wrap these in a module, but there is nothing problematic about doing exactly this in your own code.
The OP sounded like the constants will change. I.e.
sounds like different parameters could be saved and loaded (otherwise presumably they would stick to their current setup, and it sounded like they were outgrowing it.)
By the way, math constants are available through Base.MathConstants, in case you didn’t already know:
Perhaps we can help showing exactly what this means:
julia> module Const
a = 3.
b = 4.
export a, b
end
Main.Const
julia> using .Const # be aware of the dot
julia> a
3.0
julia> b
4.0
julia> a = 3
ERROR: cannot assign a value to variable Const.a from module Main
Stacktrace:
[1] top-level scope at REPL[7]:1
For this simple case of defining global constants, could someone explain for Julia beginners like me, the benefits of including a separate file containing a module wrapping all the constants, versus simple code inclusion? Thank you.
Not many, but one advantage would be that you can optionally choose not to import all constants:
julia> module Const
a = 3.
b = 4.
export a, b
end
Main.Const
julia> using .Const: a
julia> a
3.0
julia> b
ERROR: UndefVarError: b not defined
But I think we should warn that if a code depends on the definition of a lot constants, probably they should be included in a struct or other data structure and passed as parameters to the functions that will use them.
function test()
@eval begin
"Definition of x1"
const global x1 = 1
"Definition of x2"
const global x2 = 1
# many more
"Definition of xk_1"
const global xk_1 = 1
"Definition of xk"
const global xk = 1
end
end
My constants do not change.
I have a solver for some class of problems. Part of each problem are parameters. They repeat in many parts of problem definition. Thus I wanted to make use of constants to speed up calculations. Solved problem is saved with JLD2.jl so I could access it later (in different workspace) but until now I could not restore parameters as they were stored in a script.
If I changed parameters (changed problem) old setting was gone. I need function literally for a purpose of saving it.
This is a typical scenario. The most portable solutions involve storing the parameters in a struct and/or passing the model function as a parameter to the solver using closures, while the model function receives as input parameters the constants in a data structure.
Having the parameters of each model in a struct also allows very easy saving of the model data, for example using JSON.