module Mdl
b1 = false
end
import .Mdl.b1
julia> b1
false
julia> b1=true
ERROR: cannot assign a value to variable Mdl.b1 from module Main
Stacktrace:
[1] top-level scope
@ none:1
Why?
( I know, I can use a setter function for access)
module Mdl
b1 = false
end
import .Mdl.b1
julia> b1
false
julia> b1=true
ERROR: cannot assign a value to variable Mdl.b1 from module Main
Stacktrace:
[1] top-level scope
@ none:1
Why?
( I know, I can use a setter function for access)
@eval Mdl b1=true
works, but it may not be a good practice to modify variables in a module from another.
OK, @eval is another way for a write access. Mine was
function set_b1(x)
global b1 = x
end
export set_b1
within Mdl
.
But my question was “Why?”, the next one being “where is it documented?”
There are some rare situations where you want modules to be stateful. The Julian way about it seems to be to use Refs (like the Pkg global variables). You can imagine that using a ref makes changing the value a bit less complicated because the ref stays the same.
I don’t know whether the assignment of simple variables is unsupported due to complexity or what.
Example:
This is how you update a Ref value.
UPDATED_REGISTRY_THIS_SESSION[] = true
The “Why” isn’t made explicit in the documentation, but at the start it reads:
Modules are separate namespaces, each introducing a new global scope. This is useful, because it allows the same name to be used for different functions or global variables without conflict, as long as they are in separate modules.
This doesn’t explain explicitly why it isn’t straight forward allowed by just using
b1=true
or
Mdl.b1=true
But if it would be (silently) possible to do so, it is clear, that you could change a modules behaviour by accident just because you are setting a variable with the same name in your current scope. You may argue, that you have imported this variable explicitly, so you know what you do, but this may not always be the case, if there are more dependencies over serveral levels of different modules.
Well, I am on thin ice here with my reasoning, but if I have to decide for the implementation on this I would say, it’s better to have it seperated to avoid errors which are very difficult to debug.
Still one more way to get a write access through encapsulation is using structs:
module Md2
Base.@kwdef mutable struct State
b1::Bool = false
b2::Bool = false
end
const st = State()
export st
end
using .Md2
julia> st.b1
false
julia> st.b1=true;
julia> st.b1
true
I personally would prefer this one from the point of view of readability, especially if the module contains more than one state variable.
Actually as realise now, my “why” could mean multiple things:
It looks like the answer to the first two questions is negative. Would be nice to have it somehow in the documentation.
As to the the last question: I can generally understand both standpoints - “allow as much as possible” vs. “allow only what is necessary”. In this specific case, yes, I would argue this way:
but as there are workarounds, the issue ist not that important.