May someone explain the rationale behind making Symbol
s mutable? They seem to have no fields to mutate!
Where did you see something that said Symbol
s are mutable?
They are very much immutable, and (as an implementation detail) are interned as well, so that you can compare for equality simply by checking the pointers, instead of doing an O(n) comparison.
julia> isimmutable(:x)
false
That’s really strange!
Maybe you should raise an issue about that. isimmutable
returns true
for a String
pre-v0.6, but false after, and other things that also are immutable by convention and in the documentation that are implemented with a mutable struct (BigInt
, BigFloat
), also return false.
Symbols are fairly special. They are one of the few types defined in C and have special representation and special handling pretty much everywhere in the compiler, so whether the runtime thinks it’s mutable or not doesn’t really matter. That said, returning true here would be more accurate. I’ll try flipping it and see what happens.
isbits
also returns false btw.
That’s fine, it’s not. In particular, Symbols have an identity independent of their contents (the identities are linked, because Symbols are interned, but if you somehow had a different Symbol with identical contents, you’d have a problem). In particular this means that Symbols are always referenced by pointer.
Any particular reason that String
(which used to return true
in v0.5) should return false
?
Same thing for BigInt
and BigFloat
, which (at least by convention, same as String
) are considered immutable?
Well, the reflection functions answer questions about the system, not convention. It is in fact possible to mutate a BigInt and there’s valid reasons to want to do so. Regarding String
, I hope that with https://github.com/JuliaLang/julia/pull/25241 we can truthfully answer true
here.
I am aware of those reasons, but I think though that there are better ways of wrapping the underlying GMP (BigInt
) and MPFR (BigFloat
)'s structures, such that you would have faster, truly immutable types for those, with all the benefits that entails (like with the decimals in DecFP.jl
), and have a separate clean wrapper for those cases where you really do want a reference to a mutable BigInt
or BigFloat
(for example, to be able to sum up a vector of BigFloat
values.
I really like that, and I’ll add an extension to isimmutable
now for my Strs
package that returns true
, as I’d already made sure those could not be aliased to a mutable vector.