# Undefs.jl: Convenience and Experiment

**URL:** https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451
**Category:** Package Announcements
**Tags:** package, array, undef, undefinitializer
**Created:** [January 24, 2023, 10:22am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451 "2023-01-24T10:22:26Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 24, 2023, 10:22am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/1 "2023-01-24T10:22:26Z")

</div>

# Undefs.jl

I created a registered package called Undefs.jl that exports three names:

1. `undefs(A = Array, T = Float64, dims) = A{T}(undef, dims)`: a convenience method similar to `ones`, `zeros`, `trues`, and `falses`.
2. `undef!(array::Array, index=1)`: An experimental method to reset an element to an `#undef` state. This also works on `Base.RefValue`.
3. `@undef! A[1]`: A macro to make the use of the `undef!` easier.

## Demonstration of the convenience constructor, `undefs`

```julia
julia> using Undefs

julia> mutable struct Foo
           Foo(str) = finalizer(_->@async(println(str)), new())
       end

julia> undefs(5, 3)
5×3 Matrix{Float64}:
 0.0 0.0 0.0
 0.0 0.0 0.0
 0.0 0.0 0.0
 0.0 0.0 0.0
 0.0 0.0 0.0

julia> undefs(Foo, 5, 3)
5×3 Matrix{Foo}:
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef

julia> A = undefs(Array, Foo, 5, 3)
5×3 Matrix{Foo}:
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef

julia> using OffsetArrays

julia> undefs(OffsetArray, UInt8, 5, 3)
5×3 OffsetArray(::Matrix{UInt8}, 1:5, 1:3) with eltype UInt8 with indices 1:5×1:3:
 0xf0 0x7f 0x00
 0x76 0x00 0x00
 0xf1 0x00 0x00
 0x3a 0x00 0x00
 0x3f 0x00 0x00

```

## Demonstration of `@undef!`

```julia
julia> A[1] = Foo("bye world")
Foo()

julia> A
5×3 Matrix{Foo}:
    Foo() #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef

julia> @undef! A[1]

julia> A
5×3 Matrix{Foo}:
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef
 #undef #undef #undef

julia> GC.gc()
bye world

```

# Discussion

Undefs.jl is a meant as experimental convenience package and is not meant for production. The convenience constructor, `undefs` is meant to advance the conversation from recurring calls for a simpler way to allocate arrays without initialization. Additionally, the function `undef!` and the macro `@undef!` are highly experimental and use internal details of Julia’s array implementation to unassign elements from arrays of mutable structures.

[https://github.com/mkitti/Undefs.jl](https://github.com/mkitti/Undefs.jl)

While this package provides some convenient tools to play with, I encourage users to seek alternatives as described in the package README.

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [January 25, 2023, 4:40am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/2 "2023-01-25T04:40:25Z")

</div>

There’s a Base function for unsetting Array elements, if you don’t want to worry about the internal details yourself (which a prone to changing often). Undefing any other field by unsetting them is undefined behavior, and may lead to miscompilation or program crashes (pun intended)

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 25, 2023, 4:45am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/3 "2023-01-25T04:45:48Z")

</div>

This package is not meant to be taken too seriously. What’s the name of the Base function?

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 25, 2023, 4:56am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/4 "2023-01-25T04:56:17Z")

</div>

Do you mean the exported C function [`jl_arrayunset`](https://github.com/JuliaLang/julia/blob/30d11a3b2f4a557fe24cc7ba205b01dd7f0c3bc9/src/array.c#L625) ?

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [January 25, 2023, 4:57am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/5 "2023-01-25T04:57:42Z")

</div>

Yes, but I think there is also a faster version of that C function in Julia

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 25, 2023, 4:59am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/6 "2023-01-25T04:59:25Z")

</div>

`Base._unsetindex!` ?

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [January 25, 2023, 5:00am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/7 "2023-01-25T05:00:32Z")

</div>

Yes

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 25, 2023, 5:03am UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/8 "2023-01-25T05:03:25Z")

</div>

Is there a version intended for mutable structs or `Base.RefValue`?

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [January 25, 2023, 1:22pm UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/9 "2023-01-25T13:22:19Z")

</div>

No, the compiler relies on knowing it does not happen

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 25, 2023, 4:50pm UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/10 "2023-01-25T16:50:14Z")

</div>

I see. So array elements can be unset, but not elements of mutable structs like `Base.RefValue`?

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [January 25, 2023, 5:39pm UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/11 "2023-01-25T17:39:59Z")

</div>

correct

---

<div class="post-metadata">

### Author: ![Eric\_Thiebaut](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eric_thiebaut/32/28646_2.png) [@Eric\_Thiebaut](https://discourse.julialang.org/u/Eric_Thiebaut)
#### Post date: [September 5, 2025, 9:44pm UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/12 "2025-09-05T21:44:10Z")

</div>

I encountered a similar problem. From this very interesting discussion, I understand that it is only safe to unset entries in `Array` (and `Memory`), not in other structures. I also found `jl_arrayunset` and `Base._unsetindex!` but this latter function is neither documented nor `public` which seems a bit odd as it is used by some Julia packages.

BTW, to solve my problem, I have written a small package, called [`UnsetIndex.jl`](https://github.com/emmt/UnsetIndex.jl), to unset array entries and which has some overlap with `Undefs`.

`UnsetIndex` exports two symbols:

- a function `unsetindex!` which calls `Base._indexunset!` if it exists (Julia version ≥ 1.3) and otherwise calls the C function `jl_arrayunset`;
- a constant `unset` that is a singleton of a special type for which `Base.setindex!` and other base methods are extended to achieve similar results as the `@undef!` macro and more but with a more natural syntax.

To unset an entry of array `A` at index `i`, do one of:

```julia
unsetindex!(A, i)
A[i] = unset
setindex!(A, unset, i)

```

The entry is left untouched if it has a bit type. In any case, bound checking is  
performed unless `@inbounds` is active. The only restriction is that `A` must be of type  
`Array` or `Memory`.

Dot notation is supported. For example:

```julia
julia> using UnsetIndex

julia> A = split("This is a wonderful world indeed!")
6-element Vector{SubString{String}}:
 "This"
 "is"
 "a"
 "wonderful"
 "world"
 "indeed!"

julia> A[end] = unset
#undef

julia> A
6-element Vector{SubString{String}}:
    "This"
    "is"
    "a"
    "wonderful"
    "world"
 #undef

julia> A[1:2:5] .= unset
2-element view(::Vector{SubString{String}}, 1:2:3) with eltype SubString{String}:
 #undef
 #undef
 #undef

julia> A
6-element Vector{SubString{String}}:
 #undef
    "is"
 #undef
    "wonderful"
 #undef
 #undef

julia> @. A = unset
6-element Vector{SubString{String}}:
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef

```

For the last example, `A[:] .= unset` works as well and I have checked that these two are as fast as explictly writing a loop over all the elements of `A`.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [September 6, 2025, 12:25pm UTC](https://discourse.julialang.org/t/undefs-jl-convenience-and-experiment/93451/13 "2025-09-06T12:25:55Z")

</div>

> [@Eric\_Thiebaut](#):
>
> neither documented nor `public`

There is a feature request:

> <https://github.com/JuliaLang/julia/issues/58943>
>
> Currently, in order to implement an array-backed dictionary that actually frees …elements when they're \`delete!\`d, there is (as far as I am aware) no alternative to \`Base.\_unsetindex!\`.
> 
> As a consequence, you can see this function used in basically every dict-like construction outside of \`Base\`: it's in few key packages like DataStructures.jl, OrderedCollections.jl, AbstractAlgebra.jl.
> 
> I think unless we want to take the stance that "only \`Base\` is allowed to create array-backed dict-like structures that don't hold on to ghost references", there needs to be a public version of \`Base.\_unsetindex!\`.
