# Using incompletely initialized structs instead of fields of type Union{Nothing,T}

**URL:** <https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831>\
**Category:** General Usage\
**Tags:** question\
**Created:** [December 14, 2020, 10:41pm UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831 "2020-12-14T22:41:32Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [December 14, 2020, 10:41pm UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/1 "2020-12-14T22:41:33Z")

</div>

Suppose I want to define a custom type that I initialize gradually one field at a time. I could do something like this:

```julia
mutable struct A
    x::Union{Nothing, Int}
    y::Union{Nothing, Bool}
    z::Union{Nothing, String}
end

A() = A(nothing, nothing, nothing)

a = A()
a.x = 1
a.y = true
a.z = "hello"

```

However, I’m tempted to use an uninitialized struct instead, since it looks much cleaner:

```julia
mutable struct B
    x::Int
    y::Bool
    z::String
    B() = new()
end

b = B()
b.x = 1
b.y = true
b.z = "hello"

```

Is there anything wrong with the uninitialized struct approach that I take with my type `B`? I’m aware that accessing an uninitialized field raises an `UndefRefError` exception, but that seems acceptable as long as I’m only using this for my own internal code (i.e. it’s not part of a public API).

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [December 14, 2020, 11:00pm UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/2 "2020-12-14T23:00:50Z")

</div>

The risk is that you may inadvertently omit initializing a field some time. If your dataflow is such that you are sure to have all initializing field values available before utilizing the [initialized] struct, then it may be easy to refactor the logic so you do `b = B(xforb, yforb, zforb)` after having established xforb, yforb, and zforb rather than before. That way, the first method is not needed … and would buy you nothing because if you can do the second method then you are not using `nothing` values (or so it appears).

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [December 14, 2020, 11:09pm UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/3 "2020-12-14T23:09:41Z")

</div>

> [@JeffreySarnoff](#):
>
> it may be easy to refactor the logic so you do `b = B(xforb, yforb, zforb)`

Yeah, that makes sense. That’s what I normally do. However, I have a scenario where it’s easier to initialize the fields gradually. But perhaps with some careful thought I might be able to refactor. It’s a bit of a spaghetti code where I’m dynamically building up a graph with meta-data while making HTTP requests, handling errors, etc… 😂

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [December 14, 2020, 11:51pm UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/4 "2020-12-14T23:51:21Z")

</div>

> [@CameronBieganek](#):
>
> there anything wrong with the uninitialized struct approach that I take with my type `B` ? I’m aware that accessing an uninitialized field raises an `UndefRefError` exception, but that seems acceptable as long as I’m only using this for my own internal code (i.e. it’s not part of a public API).

This is not quite true. In your case the `x::Int` field will always be set (to some garbage in general). This is true for all bits types. This is a great way to introduce very subtle bugs. I would at least always set the fields of bits types to some sentinel values. This way you can still distinguish between “forgot to set it” and “set it”. If you can’t use a sentinel value, I would refrain from doing this.

---

<div class="post-metadata">

**Author:** ![dilumaluthge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dilumaluthge/32/29283_2.png) [@dilumaluthge](https://discourse.julialang.org/u/dilumaluthge)\
**Post date:** [December 15, 2020, 12:19am UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/5 "2020-12-15T00:19:51Z")

</div>

Kristoffer has this nice package: [https://github.com/KristofferC/LazilyInitializedFields.jl](https://github.com/KristofferC/LazilyInitializedFields.jl)

Maybe it would work for your use case?

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [December 15, 2020, 1:01am UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/6 "2020-12-15T01:01:39Z")

</div>

Another option if for performance reasons you wanted your struct to be immutable instead of mutable (while keeping type stability) is the following combination of `Base.@kwdef` and `Setfield.@set!`, which leads to not-too-bad-looking code.

```julia
Base.@kwdef struct A{X<:Union{Nothing,Int}, Y<:Union{Nothing,Bool}, Z<:Union{Nothing, String}}
    x :: X = nothing
    y :: Y = nothing
    z :: Z = nothing
end

a = A()
@set! a.x = 1
@set! a.y = true
@set! a.z = "hello"

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [December 15, 2020, 3:55am UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/7 "2020-12-15T03:55:13Z")

</div>

> [@thofma](#):
>
> In your case the x field will always be set (to some garbage in general). This is true for all bits types. This is a great way to introduce very subtle bugs.

Good point. I guess here I am somewhat dubiously relying on my skill as a programmer to not access fields before they are initialized. 🙂

> [@dilumaluthge](#):
>
> Kristoffer has this nice package:

Oh, nice! That looks cool. Thanks for the link!

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [December 15, 2020, 4:07am UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/8 "2020-12-15T04:07:58Z")

</div>

> [@marius311](#):
>
> Another option if for performance reasons you wanted your struct to be immutable instead of mutable (while keeping type stability) is the following combination of `Base.@kwdef` and `Setfield.@set!`

Thanks, that’s an interesting approach! I should take a closer look at Setfield.jl.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 15, 2020, 12:20pm UTC](https://discourse.julialang.org/t/using-incompletely-initialized-structs-instead-of-fields-of-type-union-nothing-t/51831/9 "2020-12-15T12:20:19Z")

</div>

> [@CameronBieganek](#):
>
> Is there anything wrong with the uninitialized struct approach that I take with my type `B` ?

I think it is best practice to make sure all the fields are initialized (or at least consistent, depending on the application) _once the constructor is done_.

Inside the constructor, you pretty much do what you like, but if an object with unassigned fields is considered valid for some purposes, the `Union{Nothing,T}` approach is preferable.
