like Revise.jl does or you use @eval ThatModule some_global = 10.
Regarding testm.f = g, there’s a technical reason for not allowing assigning to a function. Julia has multiple dispatch, and it would make the compiler’s job much harder/impossible if it gave you the option to redefine functions like that.
You can’t write testm.f(x) = g(x) inside of a function, to redefine it at runtime. This restriction allows the compiler to assume that, once you’re pressed Enter at the REPL, f(x) = g(x) will be true until the computation finishes (barring some technicality with @eval and the world age).
Globals can be changed at runtime anywhere, so the compiler can’t assume anything about them, and their performance is terrible.
That’s why functions and globals are separate concepts in Julia, whereas in Python function definitions are (basically) implemented as global variables.
I am not sure what the original design reason was, but I like it this way. I consider globals as internal to a module, mostly an implementation detail, which should only be exposed via accessor functions outside the module.
Eg suppose I have a package for managing some templates, and have a setup like
Later on I can decide to make the global a Ref, fixing the type, or allow the user to set it via an environment variable and just provide a fallback, eg
function default_template_dir()
get(ENV, "DEFAULT_TEMPLATE_DIR", DEFAULT_TEMPLATE_DIR)
end
without changing the API. Similarly, I can make a setter function
function default_template_dir!(path)
isdir(path) || @warn "setting non-existent path for templates"
DEFAULT_TEMPLATE_DIR = path
end
I’ve been experimenting a lot with similar issues related to dependency injection, and my current preferred approach is to eval within the scope of the targeted module. So if you’re looking for a way to actually do what you tried, this works: