I’ve found myself doing things like the below out of convenience. I’ve noticed that type stability is destroyed however. Is there a better way of achieving the same thing?
The reason I’m doing this because the functions keep a reference to the original objects. This means I can close a function over a mutable struct, then later update it, and these changes are reflected in the closure:
julia> mutable struct Foo{T}
a::T
end
julia> (foo::Foo)() = foo.a
julia> foo = Foo(1)
Foo{Int64}(1)
julia> bar() = foo()
bar (generic function with 1 method)
julia> bar()
1
julia> foo.a = 2
2
julia> bar()
2
Marking a global as const tells the compiler that the variable is not going to change (neither value nor type) since constants will only be assigned once. Be aware that this only works for global scope. See here.
julia> foo.a = Bar(2.0)
ERROR: MethodError: Cannot `convert` an object of type Bar{Float64} to an object of type Bar{Int64}
Closest candidates are:
convert(::Type{T}, ::T) where T at essentials.jl:154
Bar{Int64}(::Any) where T at REPL[1]:2
Stacktrace:
[1] setproperty!(::Foo{Bar{Int64}}, ::Symbol, ::Bar{Float64}) at ./sysimg.jl:19
[2] top-level scope at none:0
Neither of those has anything to do with const. Const does not make a mutable object immutable, so there’s nothing wrong with modifying its field. It only requires that the binding (the label foo) is not reassigned to some other object.
The second case also has nothing to do with const, and you’ll get the same error without a const declaration. It’s simply a matter of trying to set a field with a value of the wrong type.
Note that “constant-ness” does not extend into mutable containers; only the
association between a variable and its value is constant. If x is an array or
dictionary (for example) you can still modify, add, or remove elements.
But feel free to put up a PR with improved wording.
Having thought about it, and considered the examples in this post, the explanation in the docs covers everything. I suppose I just had a mental block changing from c++ const to Julia const.
My tuppence on the subject that I expect that a lot of c++ focused developers will have raised eyebrows when the language even allows them to change something prefixed by const regardless of the warning. I for one would have better understood a word like consttype or fixedtype, or something entirely different like strong, to embody the qualities of const.
Yeah, I think it just comes down to the fact that C/C++ has two kinds of const-y pointers: a const pointer and a pointer-to-const, and they do completely different things: one stops you from changing what address the pointer points to and the other stops you from modifying whatever is at that address.
Julia handles things differently: mutability is a property of the object (mutable struct vs. struct), so the only thing a const annotation can do is inform the language that a particular binding will always refer to the same value. So Julia consts behave essentially like (I think…) const pointers, and not like pointers-to-const.