# Dynamic Union

**URL:** <https://discourse.julialang.org/t/dynamic-union/18642>\
**Category:** General Usage\
**Created:** [December 13, 2018, 10:19pm UTC](https://discourse.julialang.org/t/dynamic-union/18642 "2018-12-13T22:19:26Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Qiyamah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qiyamah/32/2660_2.png) [@Qiyamah](https://discourse.julialang.org/u/Qiyamah)\
**Post date:** [December 13, 2018, 10:19pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/1 "2018-12-13T22:19:26Z")

</div>

Hi,

I can do this in coding phase.

```nohighlight
const SymExpr = Union{Symbol,Expr}
:s isa SymExpr # returns true
:(x+1) isa SymExpr # returns true
1 isa SymExpr # returns false

```

I want a dynamic Union so that I can add Int to it at runtime and the check 1 isa SymExpr return true?

Can I do this? If so what is the proper way

Thanks

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 13, 2018, 10:24pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/2 "2018-12-13T22:24:00Z")

</div>

Don’t think that is possible, since `Union` types are immutable

```nohighlight
julia> x = Union{Float64,Array}
Union{Float64, Array}

julia> x.a
Float64

julia> x.a = Int
ERROR: type Union is immutable
Stacktrace:
 [1] setproperty!(::Type, ::Symbol, ::Type) at ./sysimg.jl:16
 [2] top-level scope at none:0

```

You could keep an array of types and check `typeof(x) in SymExpr`, where `SymExpr = [Symbol,Expr,Int]`, then you could add to the array.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 13, 2018, 10:29pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/3 "2018-12-13T22:29:59Z")

</div>

You want to keep a variable keeping a list of types that you can add `Int` to?

Just `SymExpr = Union{SymExpr,Int}`?

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [December 14, 2018, 3:47am UTC](https://discourse.julialang.org/t/dynamic-union/18642/4 "2018-12-14T03:47:05Z")

</div>

If you want to change SymEpr at runtime but do not want to incur type-instability costs you can make it a reference.

```julia
julia> const SymExpr = Ref(Union{Symbol,Expr})
Base.RefValue{Union}(Union{Expr, Symbol})

julia> 1 isa SymExpr[]
false

julia> SymExpr[] = Union{SymExpr[],Int}
Union{Int64, Expr, Symbol}

julia> 1 isa SymExpr[]
true

```

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 14, 2018, 8:47am UTC](https://discourse.julialang.org/t/dynamic-union/18642/5 "2018-12-14T08:47:49Z")

</div>

You could use a trait:

```julia
struct SymExpr end
SymExpr(::Expr) = SymExpr()
SymExpr(::Symbol) = SymExpr()
SymExpr(::Any) = nothing

SymExpr(:a) isa SymExpr # -> true
SymExpr(1) isa SymExpr # false
SymExpr(::Int) = SymExpr()
SymExpr(1) isa SymExpr# true

```

see [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/#Trait-based-dispatch-1).

---

<div class="post-metadata">

**Author:** ![Qiyamah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qiyamah/32/2660_2.png) [@Qiyamah](https://discourse.julialang.org/u/Qiyamah)\
**Post date:** [December 14, 2018, 11:05pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/6 "2018-12-14T23:05:59Z")

</div>

I am sorry maybe I haven’t conveyed the idea to the fullest extent.

What I want to do is:

```julia
SymExpr = Union{Symbol,Expr}
f(x::SymExpr) = println(x)
f(:a) #prints a
f(:(x+1)) #prints x+1
f(1) # ERROR: MethodError: no method matching f(::Int64)
SymExpr = Union{SymExpr,Int}
f(1) # Still ERROR.

```

I want the last f(1) call to dispatch correctly.

Thanks

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 14, 2018, 11:12pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/7 "2018-12-14T23:12:36Z")

</div>

Why would you not want to have `Int` in your union in the first place? Why does it need to be dynamic? Are you only going to add `Int` to it, or is there a more general pattern you need to satisfy?

I’m trying to understand more about your motivations behind this.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 14, 2018, 11:26pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/8 "2018-12-14T23:26:22Z")

</div>

The only way to change dispatch is to define (or delete…) methods so no you can’t do anything else and change dispatch. You can always add your own type check that is as dynamic as you want though.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 16, 2018, 9:03am UTC](https://discourse.julialang.org/t/dynamic-union/18642/9 "2018-12-16T09:03:25Z")

</div>

Have you read the link I posted above? It tells you how to do it:

```julia
struct SymExpr end
SymExpr(::Expr) = SymExpr()
SymExpr(::Symbol) = SymExpr()
SymExpr(::Any) = nothing

# Do the trait dispatch
# f(::SymExpr) = 1
# needs to be written as
f(x) = _f(SymExpr(x), x)
_f(::SymExpr, x) = 1
_f(::Nothing, x) = 2 # or leave it away for a method error

f(:a) # 1
f(1) # 2
SymExpr(::Int) = SymExpr()
f(1) # 1

```

If you can’t be bothered with writing out the trait-dispatch (and you just need a simple trait-dispatch setup) then you can use [https://github.com/mauro3/SimpleTraits.jl](https://github.com/mauro3/SimpleTraits.jl)

```julia
using SimpleTraits
@traitdef SymExpr{X}
@traitimpl SymExpr{Expr}
@traitimpl SymExpr{Symbol}

@traitfn f(::::SymExpr) = 1
@traitfn f(::::!(SymExpr)) = 2 # again, not defining this will just give a Method error
f(:a) # 1
f(:(1+1)) # 1
f(1) # 2
@traitimpl SymExpr{Int}
f(1) # 1

```

---

<div class="post-metadata">

**Author:** ![Qiyamah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qiyamah/32/2660_2.png) [@Qiyamah](https://discourse.julialang.org/u/Qiyamah)\
**Post date:** [December 16, 2018, 6:58pm UTC](https://discourse.julialang.org/t/dynamic-union/18642/10 "2018-12-16T18:58:48Z")

</div>

I thank you very much for your kind answer mauro3.  
I have figured out a similar way to yours, I have my own traits package.  
One of the reasons I asked that question to see what type level programming utilities Julia is providing.  
Thanks
