I'm looking at some older code, and I see const None = Union{}
. I get the feeling that this originated with some old Julia version. Does anyone know if that was the case?
Was this an older version of nothing
?
Hm, I don't know the history here but I assume not. Union{}
can't be instantiated as a value whereas Nothing
can. That means that Union{}
only exists as a type level construct
Nowadays, we call Union{}
by the name TypeofBottom
, meaning it's the 'bottom' of the type hierarchy (where Any
is the top)
Right, so that shows that None
was not an early version of Nothing
Perhaps to be concrete, I'm currently looking at https://github.com/jheinen/GR.jl/blob/master/src/GR.jl#L250-L253 . I'm thinking these globals should be converted to const Ref
but I would need a fixed type or a perhaps a Union
.
Yeah, that's tricky. Do you know how many possible types this variable can take on?
I think most of these could be directly converted to Union{Nothing, String}
or Union{Nothing, Int}
. In the String
case, it looks like we might be able to use empty string. In the Int case, a negative sentinel might work instead.
Perhaps the other question then is how performant is
julia> r = Ref{Union{Nothing,Int}}(5)
Base.RefValue{Union{Nothing, Int64}}(5)
julia> r[] = nothing
julia> r[] = 5
5
It's extremely efficient - usually optimally efficient. Especially when used with heap-allocated structs
A Union{Nothing, String} takes up only 8 bytes
And on master, a few important improvements to the compiler means that unions are handled more efficiently. So the only issue is e.g. Union{Int, Nothing} being 16 bytes.
Edit: Turns out I was wrong - it's only optimized for bitstypes.
Last updated: Dec 28 2024 at 04:38 UTC