# Union{Some{T}, Nothing} behaviour

**URL:** https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353
**Category:** New to Julia
**Created:** [March 17, 2021, 1:54am UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353 "2021-03-17T01:54:38Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)
#### Post date: [March 17, 2021, 1:54am UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/1 "2021-03-17T01:54:38Z")

</div>

I cannot figure out how to obtain a non-nothing output from the following code.

```julia
julia> struct B
           a::Union{Some{T}, Nothing} where {T<:Integer}
       end

julia> b = B(nothing)
B(nothing)

julia> b = B(5)
ERROR: could not compute non-nothing type
Stacktrace:
 [1] error(s::String)
   @ Base .\error.jl:33
 [2] nonnothingtype_checked(T::Type)
   @ Base .\some.jl:31
 [3] convert(#unused#::Type{Union{Nothing, Some{T}} where T<:Integer}, x::Int64)
   @ Base .\some.jl:36
 [4] B(a::Int64)
   @ Main .\REPL[99]:2
 [5] top-level scope
   @ REPL[101]:1

```

---

<div class="post-metadata">

### Author: ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)
#### Post date: [March 17, 2021, 2:25am UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/2 "2021-03-17T02:25:53Z")

</div>

Can you elaborate what you want to achieve?

---

<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: [March 17, 2021, 2:31am UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/3 "2021-03-17T02:31:32Z")

</div>

The default constructor is trying to convert `5` to a `Union{Some{T}, Nothing} where {T<:Integer}`, but it doesn’t know how:

```julia
julia> convert(Union{Some{T}, Nothing} where {T <: Integer}, 5)
ERROR: could not compute non-nothing type
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] nonnothingtype_checked(::Type{T} where T) at ./some.jl:29
 [3] convert(::Type{Union{Nothing, Some{T}} where T<:Integer}, ::Int64) at ./some.jl:34
 [4] top-level scope at REPL[1]:1

```

You could provide a constructor for your type. Perhaps something like this:

```julia
B(x::Integer) = B(Some(x))

```

---

<div class="post-metadata">

### Author: ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)
#### Post date: [March 17, 2021, 2:32am UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/4 "2021-03-17T02:32:16Z")

</div>

I would write this as the following, which reveals why this pattern is harder to use in practice unless you make `T` explicit more often:

```julia
julia> struct B{T <: Integer}
           a::Union{Some{T}, Nothing}
       end

julia> B(nothing)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] B(a::Nothing)
   @ Main ./REPL[1]:2
 [2] top-level scope
   @ REPL[2]:1

julia> B(Some(1))
B{Int64}(Some(1))

julia> B{Int}(nothing)
B{Int64}(nothing)

```

The problem is that you can’t figure out what `T` is without explicitly specifying it or providing a concrete input value that lets it be determined. It’s like the problem of assigning a type to an empty array – the thing that would give you the relevant information isn’t present, so you need to make up for that absence.

---

<div class="post-metadata">

### Author: ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)
#### Post date: [March 17, 2021, 3:17pm UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/5 "2021-03-17T15:17:37Z")

</div>

> [@giordano](#):
>
> Can you elaborate what you want to achieve?

In this particular case I am trying to model a drive train. Think of a motor driving a gearbox driving a machine. Sometimes it may be more than one gearbox. Let’s call:  
the motor: shaft 1  
the coupling: connector 1  
the gearbox input : shaft 2  
the gearbox: connector 2  
the gearbox output: shaft 3  
the coupling: connector 4  
the driven machine: shaft 4

I would like a structure that holds the information for each shaft and another that holds the information for each component.  
The shaft structure has information for the previous shaft, the following shaft and the component that connects between the current shaft and the following shaft. My thought was to use nothing as the previous shaft for the motor, where there is no previous shaft. Perhaps a better way would be a separate structure for this shaft, where the absence of that field would indicate that there is no previous shaft?

In reading the documentation and on discourse, it seemed that the Union{Some{T}, Nothing} might be a good way of indicating that there is a shaft present or that nothing is present.

---

<div class="post-metadata">

### Author: ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)
#### Post date: [March 17, 2021, 3:27pm UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/7 "2021-03-17T15:27:36Z")

</div>

Thanks johnmyleswhite, that is most helpful.

For my purposes, {T::Int} may be just as good as {T\<:Integer}, if this makes life easier for the compiler. Experimenting shows {T \<: Int} works but {T :: Int} does not.

I see an inconsistency in passing nothing versus something to the field. So I experimented with doing away with Some and using the following which seems to provide a more consistent interface:

```julia
julia> struct B{T <: Int}
           a::Union{T, Nothing}
       end

julia> B{Int}(5)
B{Int64}(5)

julia> B{Int}(nothing)
B{Int64}(nothing)

julia> isnothing(ans.a)
true

julia>

```

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [March 17, 2021, 3:30pm UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/8 "2021-03-17T15:30:46Z")

</div>

There is no point in parametrizing `T` here.

```julia
struct B
    a::Union{Int, Nothing}
end

```

should be functionally equivalent.

Edit: Spoke to soon, `B{Union{}}(nothing)` is still valid with your version, but not with mine, so that might be a reason to explicitly parametrize `T`.

---

<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: [March 17, 2021, 3:51pm UTC](https://discourse.julialang.org/t/union-some-t-nothing-behaviour/57353/9 "2021-03-17T15:51:44Z")

</div>

> [@Jake](#):
>
> Perhaps a better way would be a separate structure for this shaft

This seems to me like the best approach. Don’t be afraid to introduce new types for components that are different from each other. I try to avoid types that are filled with `nothing` values. If a type is filled with a bunch of `nothing` values, then it probably should be a different type without the `nothing`s.

> [@Jake](#):
>
> where the absence of that field would indicate that there is no previous shaft?

Types normally have some semantic meaning beyond just the structure of their fields. So if you have a `Motor` type, without looking at the fields you know that it does not have a previous shaft, because motors simply don’t have previous shafts.

> [@Jake](#):
>
> In reading the documentation and on discourse, it seemed that the Union{Some{T}, Nothing} might be a good way of indicating that there is a shaft present or that nothing is present.

I think the use of `Some` is overkill here. In my understanding, `Some` is only used in fairly specialized situations where you are trying to distinguish between the value `nothing` and literal nothingness. From the docstring, `Some` is

> a wrapper type used in `Union{Some{T}, Nothing}` to distinguish between the absence of a value (`nothing`) and the presence of a `nothing` value (i.e. `Some(nothing)`).

As an example, suppose you have a dictionary of type `Dict{Int, Union{Int, Nothing}}`. There’s a difference between keys that don’t exist in the dictionary and keys that do exist in the dictionary but which have the value `nothing`.
