Unfortunately I believe that the optimizations are only possible when T
is of reference type and not plain data, because in the former case one could use the NULL
pointer to represent the nothing
. If T
is plain data then I believe that Union{T,Nothing}
requires a hidden flag behind the scene to identify which variant is currently in use. This penalizes the plain data case (Int
, Float64
, …), which is admittedly the most interesting. I might be completely wrong about this; this is just my current understanding. (A bit like rust can optimize Option<&'a T>
because references are never null.)
I will try to run some benchmarks as soon as I have implemented all 43 versions of the same code
It removes it here, but it introduces it as soon as you want heterogeneous collections
Vector{P{T,X,Y} where {X<:Union{T,Nothing}, Y<:Union{T,Nothing}}}
which is something that I want. This approach wouldn’t work for me I think.
That forces you to collate two a priori independent variables (think of a name and an age) for no good reason. Imagine a situation where you always know either the name or the age:
struct S
name_or_age::Union{String, Int}
...
end
This doesn’t look very good.
In the most general situation, again, it might not be straightforward to take into account all possible combinations of “definedness” of the fields, and arbitrarily grouping them under the same name seems a path to insanity.
If I weren’t super concerned with performance I would definitely go with the Union{T,Nothing}
approach, which at least expresses the semantic adequately. I’ll come back with some benchmarks if I manage to get some meaningful ones.