struct MMX
x
MMX() = new()
end
t = MMX()
> MMX(#undef)
typeof(t.x)
Basically I am asking what is the type of field x in this case?
struct MMX
x
MMX() = new()
end
t = MMX()
> MMX(#undef)
typeof(t.x)
Basically I am asking what is the type of field x in this case?
Weird but interesting question…
julia> typeof(undef)
UndefInitializer
julia> typeof(UndefInitializer)
DataType
dump(undef)
UndefInitializer array initializer with undefined values
show(undef)
array initializer with undefined values
https://github.com/JuliaLang/julia/blob/0b80774b9f0a517f12714e30808915e99fd916ff/base/boot.jl#L402
Apparently it’s a quintessential empty struct!
julia> struct OO
x
end
julia> OO(undef)
OO(array initializer with undefined values)
julia> t = ans
OO(array initializer with undefined values)
julia> t.x
array initializer with undefined values
I don’t think what you say is quite right because in the former case
struct MMX
x
MMX() = new()
end
t = MMX()
julia> t.x
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getproperty(::Any, ::Symbol) at ./Base.jl:20
I’d say it’s Union{}
.
If so, how can I instantiate Union{} or I can ask this question another way, How can I create and undefined reference object if something like that exists.
You can’t create an undefined reference object, but that is exactly the point. It stands for a stack-allocated object, that has not been defined yet. A classic use case is for vectors, e.g. Vector{SomeType}(undef, n)
, whose values will be overwritten anyways, so there’s no need to fill them with a value. undef
is just a singleton object signifying, that a vector or a mutable struct does not need to be initialized. If SomeType
is heap-allocated, on the other hand, it will just be some random value that has been in this location in memory, so this shouldn’t usually be relied upon. The reason this works for your type MMX
is that x
is of type Any
, which means it is boxed, so it can be #undef
.
If you agree that any “thing” inside of a Vector{T}
is of type T
, then my argument follows from the observation
julia> resize!(Union{}[], 1)
1-element Array{Union{},1}:
#undef
It is also compatible with that Union{} <: T
holds for any type T
. So you can “put” #undef
inside of any arrays:
julia> Union{} <: Some
true
julia> resize!(Some[], 1)
1-element Array{Some,1}:
#undef
julia> Base._return_type(getindex, (Vector{Some}, Int))
Some
julia> ans == Union{Union{}, Some}
true
(Everything I said here just “kind of” makes sense.)
Generally, values have types, and for your example there is no value yet (hence #undef
). So t.x
will raise an error, and typeof(t.x)
cannot be executed as such.
So, in a sense, the question is meaningless. #undef
was introduced precisely to signal this: it is not a value per se, just a way of signaling that there is no value.
you can think of the type as Int