# What about an \`undefs\` function in \`Base\`?

**URL:** <https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690>\
**Category:** General Usage\
**Tags:** feature-request\
**Created:** [January 9, 2023, 2:18am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690 "2023-01-09T02:18:50Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [January 9, 2023, 2:18am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/1 "2023-01-09T02:18:50Z")

</div>

It would be nice to have an `undefs` function that operates the same way as `zeros` and `ones`. The syntax for initializing an array of `zeros` or `ones` is more concise than initializing an array of `undefs` but is not as efficient. I know use cases can be different but I’m simply taking about initializing an array that will be filled in it’s entirety later on. `zeros` and `ones` will be much more intuitive to new users that don’t fully understand Julia’s type declaration. For this reason I suspect many novice Julia users use `zeros` and `ones` when they should really be reserving an array of `undefs`. To rectify this I propose adding an `undefs` function in `Base` unless there is a good reason not to.

e.g.

```julia
zeros(Float32,10,10)
ones(Int8,10,10)

# vs
Array{Int16}(undef,10,10)

```

---

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [January 9, 2023, 2:52am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/2 "2023-01-09T02:52:41Z")

</div>

Here’s some discussion from 2020: [Simpler syntax for creating uninitialized arrays · Issue #34775 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/34775)

Basically, it was considered, but there wasn’t consensus to put it in (the way of many things in a carefully-designed language).

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [January 9, 2023, 3:02am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/3 "2023-01-09T03:02:17Z")

</div>

OK, it looks like this has been discussed at length… and there was even a [PR for this](https://github.com/JuliaLang/julia/pull/42620). We should let sleeping dogs lie.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [January 9, 2023, 7:30am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/4 "2023-01-09T07:30:39Z")

</div>

> [@alex-s-gardner](#):
>
> We should let sleeping dogs lie.

Maybe so. But after having quick-read the PR, I still don’t see many (good) arguments against it. It seems that the PR has been closed (by the author himself) mainly because he realized that a `calloc`-based `zeros` could make an `undefs` function obsolete. Even if one agrees with this, we still aren’t using `calloc` for `zeros` (see [this PR](https://github.com/JuliaLang/julia/issues/130)). I know that @mkitti (the author of the PR) has in the mean time created [ArrayAllocators.jl](https://github.com/mkitti/ArrayAllocators.jl) which provides a `calloc` interface. But I don’t see that the question asking for an `undefs` in `Base` has been resolved in this PR.  
The linked discourse thread has a few more arguments but also doesn’t really seem to have come to a conclusion (but rather just ended after a few exchanges).

FWIW, personally, I’m with @StefanKarpinski on this ([Simpler syntax for creating uninitialized arrays · Issue #34775 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/34775#issuecomment-592983243)):

> One thing we could do is:
> 
> - make `Array{T}(zeros, dims...)` etc. work
> - make `undef(T, dims...)` and `undef(dims...)` work
> 
> That way we round out the collection of convenience constructors in way that can always be expressed in terms of the fuller `Container{Eltype}(initializer, dims...)` form.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 9, 2023, 8:39am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/5 "2023-01-09T08:39:09Z")

</div>

> [@alex-s-gardner](#):
>
> For this reason I suspect many novice Julia users use `zeros` and `ones` when they should really be reserving an array of `undefs`.

I believe that there’s an argument that novice users should probably not use `undef` arrays, that it is an advanced concept used for achieving micro optimization, and easy to misuse. Not sure if that’s right or not, but in many cases you can use the very convenient `similar` function.

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [January 9, 2023, 5:42pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/6 "2023-01-09T17:42:35Z")

</div>

I’m not sure I agree with those arguments. `undef` is a more advanced concept but for people new to Julia coming from other languages they will likely have a clear understanding of per-allocating and an `undefs` function would be no more dangerous than `similar` but would have the same syntax as `ones` and `zeros` that are heavily used for per-allocating. It only takes using `undefs` or `similar` once to realize the dangers. Also, depending on ones workflow (i.e. large arrays) I would argue that using `undefs` in place of `zeros` or `ones` can result in significant speedup. Having new users come and immediately discover speedups through using of `undefs` and become accustom to working with `undef` arrays would be a good thing.

```julia

julia> @btime zeros(10000,10000)
  186.795 ms (2 allocations: 762.94 MiB)
10000×10000 Matrix{Float64}

julia> @btime Array{Float64}(undef,10000,10000)
  6.972 μs (2 allocations: 762.94 MiB)
10000×10000 Matrix{Float64}

```

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [January 9, 2023, 7:10pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/7 "2023-01-09T19:10:55Z")

</div>

Although I’d argue if those speedups make a noticeable difference to the runtime of your program you should probably reconsider your algorithm and think about reusing buffers (which is probably why @DNF calls it a micro optimization - if you’re calling `zeros` often enough for that millisecond difference to matter there’s likely a bigger issue with the algorithm)

---

<div class="post-metadata">

**Author:** ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)\
**Post date:** [January 9, 2023, 8:23pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/8 "2023-01-09T20:23:23Z")

</div>

One thing is that undefs might lie to you, and not allocate the memory at all until you try and write to it.

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [January 9, 2023, 9:29pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/9 "2023-01-09T21:29:15Z")

</div>

Fair point re. speed. I think using undef is still best practice in many cases.

---

<div class="post-metadata">

**Author:** ![Tbl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbl/32/5984_2.png) [@Tbl](https://discourse.julialang.org/u/Tbl)\
**Post date:** [January 10, 2023, 1:41pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/10 "2023-01-10T13:41:48Z")

</div>

I would also advocate for `undefs`. I am teaching scientific computing in Julia at university level and I prefer to familiarize student with some basic optimization concepts. I find it strange that language which considers itself to be designed for it makes it more ~~obtuse~~ obscure to initialize array and do nothing then initialize array and fill it. It is not a big deal, but it’s awkward.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 10, 2023, 1:54pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/11 "2023-01-10T13:54:55Z")

</div>

But it _is_ very straightforward to do today:

```julia
Vector{T}(undef, n)
similar(X)

```

It is not an undue burden to learn this, I think.

---

<div class="post-metadata">

**Author:** ![Tbl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbl/32/5984_2.png) [@Tbl](https://discourse.julialang.org/u/Tbl)\
**Post date:** [January 10, 2023, 2:12pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/12 "2023-01-10T14:12:26Z")

</div>

It is more ~~obtuse~~ obscure than `zeros` or `ones`, that is a point which is being made.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 10, 2023, 2:18pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/13 "2023-01-10T14:18:26Z")

</div>

Yes, but only a bit. And it _is_ also a more obscure subject (I presume you meant ‘obscure’).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 10, 2023, 2:20pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/14 "2023-01-10T14:20:56Z")

</div>

BTW, I tried to make an implementation. It’s type piracy, not sure if there are any possible repercussions to using it:

```julia
(::UndefInitializer)(::Type{T}, siz::NTuple{N, Integer}) where {T, N} = Array{T, N}(undef, siz)
(::UndefInitializer)(::Type{T}, siz::Integer...) where {T} = undef(T, siz)
(::UndefInitializer)(siz...) = undef(Float64, siz...)

```

Examples:

```julia
julia> undef(Int, (2,3))
2×3 Matrix{Int64}:
 1 0 0
 1 0 0

julia> undef(Int, 2,3)
2×3 Matrix{Int64}:
 2688559218696 2688559218696 2688559218696
 2688559218696 2688559218696 2688559218928

julia> undef(2,3)
2×3 Matrix{Float64}:
 0.0 0.0 0.0
 0.0 0.0 0.0

julia> undef(String, 2,3)
2×3 Matrix{String}:
 #undef #undef #undef
 #undef #undef #undef

```

This seems a bit odd, perhaps:

```julia
julia> undef()
0-dimensional Array{Float64, 0}:
0.0

```

It makes sense, but it’s not completely obvious that the default type should be `Float64`, unlike with `zeros` and `ones`.

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [January 11, 2023, 7:04pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/15 "2023-01-11T19:04:21Z")

</div>

I think the function name should be `undefs` as it fits with the `zeros` and `ones` family. This would also avoid Type piracy.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [January 11, 2023, 7:56pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/16 "2023-01-11T19:56:49Z")

</div>

> [@DNF](#):
>
> novice users should probably not use `undef` arrays

Why is that? If I want to iterate over an array and store the results in the same sized array, what is the best practice?

```julia
do_stuff(val) = string(val)
input_vec = [1,2,3]
# Broadcast obviously works for such a small thing
output_vec = do_stuff.(input_array)

# But for more complicated processes, the best paradigm I know is
output_array = Vector{String}(undef, length(output_array))
for i in eachindex(input_array)
    #more logic
    output_array[i] = do_stuff(input_array[i])
end

```

What should I do besides this?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 11, 2023, 11:00pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/17 "2023-01-11T23:00:53Z")

</div>

There’s nothing wrong with your code, as far as I can tell. Alternatively, you could use `map() do` or make a more complicated function to broadcast.

I have nothing against people using `undef`, I also do.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 11, 2023, 11:04pm UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/18 "2023-01-11T23:04:51Z")

</div>

> [@alex-s-gardner](#):
>
> I think the function name should be `undefs`

If there’s going to be a new name, I think I would prefer `allocate`, or something like that.

Perhaps things would be more neat and tidy if there were just `allocate` and `fill`. Then there wouldn’t be the confusion between `zeros` and `zero`, `ones` and `one`.

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [January 12, 2023, 3:18am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/19 "2023-01-12T03:18:26Z")

</div>

> [@DNF](#):
>
> I think I would prefer `allocate`,

My personal preference would be to use `undefs` as the `ones` and `zeros` convention has already been decided on. The further we get from `undefs` the less useful it will be over already existing syntax for defining `undef` arrays

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [January 12, 2023, 8:00am UTC](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690/20 "2023-01-12T08:00:30Z")

</div>

One problem that I haven’t seen mentioned here with the suggested `undefs` is that it does not generalize beyond `Array`. `zeros` and `ones` have the same problem and before Julia 1.0 there were even plans to _remove_ `zeros` and `ones` (see e.g. [JuliaLang/julia#24444](https://github.com/JuliaLang/julia/issues/24444), [JuliaLang/julia#25507](https://github.com/JuliaLang/julia/pull/25507)) rather than adding more similar functions.

Julia and packages defined hundreds of different array types and there is no consistent way to initialize them, not even for getting a zero-array. For example, given `FooArray`, how do you instantiate one filled with zeros? A good guess is probably something like `FooArray(zeros(n))`, but i) that doesn’t always work, and ii) it also feels wrong to have to construct an `Array` first. It is true that in many cases there will be an `Array` backing the `FooArray`, but that should then IMO be allocated and managed internally and hidden from the user. [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) have “solved” this with macros (`@SVector zeros(3)` etc) which doesn’t actually call the `Array`-specific `zeros` function, but just like `zeros` this does not generalize.

The current `Array{T}(undef, n)` implementation came from the idea of having a general array “constructor interface” of the form `ArrayType{T}(initializer, size, ...)`, but only `undef`, `nothing` and `missing` exist as initializers now. There were attempts to also have `Array{T}(zeros, size)` and `Array{T}(one(s), size)` as replacements or generalizations of `zeros` and `ones`, see [JuliaLang/julia#24389](https://github.com/JuliaLang/julia/pull/24389).

Much discussion around this can be found in [JuliaLang/julia#24595](https://github.com/JuliaLang/julia/issues/24595) and linked issues/PRs.

[Next page](https://discourse.julialang.org/t/what-about-an-undefs-function-in-base/92690.md?page=2)
