Yes, these methods (fill
, similar
, collect
, comprehension
, …) use an array constructor (well, at least I assume so - I have only checked a few). For example, in array.jl
we have
fill(v, dims::NTuple{N, Integer}) where {N} = (a=Array{typeof(v),N}(undef, dims); fill!(a, v); a)
Thus, in this case the array is constructed with the undef initializer, and then filled with fill!
.
The construction methods appears to be defined in boot.jl
. For example, the 1d case looks like this.
Array{T,1}(::UndefInitializer, m::Int) where {T} =
ccall(:jl_alloc_array_1d, Array{T,1}, (Any, Int), Array{T,1}, m)
Digging deeper, in array.c
we see that jl_alloc_array_1d
does its job via
static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims,
int8_t isunboxed, int8_t hasptr, int8_t isunion, int8_t zeroinit, size_t elsz)
This method allocates memory, and perform initialization if needed (nullptrs when storing reference).
Now, if jl_alloc_array_1d
is viewed as a “language internal” function (don’t know if this is the case), then one could define
function Array{T,1}(::InitializerFunction, m::Int, initializer) where {T}
a = ccall(:jl_alloc_array_1d, Array{T,1}, (Any, Int), Array{T,1}, m)
for i = 1:m
a[i] = initializer(i)
end
a
end
or something more though through in the same vein.
Then one could define fill
without undef like
fill(v, dims::NTuple{N, Integer}) where {N} = Array{typeof(v),N}(InitializerFunction(), dims, () -> v)
If jl_alloc_array_1d
is a user exposed function, then I guess the modifications would go into _new_array_
.
Out of curiosity, do you have example for use cases that need uninitialized arrays storing reference type data?
As I said before, I think for most use cases the vectors can be initialized immediately,
and in other cases Union{T, Nothing}
could be used. And, I’m curious to know if there a big gaps in my thinking here, and in that case what those are.
Another thing that probably would help, is to make vectors distinguish between capacity and size. This would make it possible to have a partially (in a controlled way) initialized vector - the uninitialized part would be out of bounds. Thus making it more convenient to initialize the vector.