# Unstable type with dispatch by Val{:X}() with 5 functions

**URL:** https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072
**Category:** Performance
**Created:** [October 9, 2020, 10:45pm UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072 "2020-10-09T22:45:12Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)
#### Post date: [October 9, 2020, 10:45pm UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/1 "2020-10-09T22:45:12Z")

</div>

When i use following code i have no problems with types

```julia
using LinearAlgebra, BlockDiagonals
function f1(x::Vector{T}, ::Int, ::Val{:A}) where T
    Diagonal(x)
end
function f1(x::Vector{T}, i::Int, ::Val{:B}) where T
    Diagonal(x .* i)
end
function f1(x::Vector{T}, ::Int, ::Val{:C}) where T
    Diagonal(x)
end
function f1(x::Vector{T}, ::Int, ::Val{:D}) where T
    Diagonal(x)
end
function f2(x1, x2, a, b)
    x = Vector{Matrix}(undef, 2)
    x[1] = f1(x1, 2, Val{a}())
    x[2] = f1(x2, 3, Val{b}())
    BlockDiagonal(x)
end
@code_warntype f2([1,2,3], [2,3,4], :A, 

```

@code\_warntype:

```julia
#self#::Core.Compiler.Const(f2, false)
  x1::Array{Int64,1}
  x2::Array{Int64,1}
  a::Symbol
  b::Symbol
  x::Array{Array{T,2} where T,1}

Body::Union{}
1 ─ %1 = Core.apply_type(Main.Vector, Main.Matrix)::Core.Compiler.Const(Array{Array{T,2} where T,1}, false)
│ (x = (%1)(Main.undef, 2))
│ %3 = Core.apply_type(Main.Val, a)::Type{Val{_A}} where _A
│ %4 = (%3)()::Val{_A} where _A
│ %5 = Main.f1(x1, 2, %4)::Diagonal{Int64,Array{Int64,1}}
│ Base.setindex!(x, %5, 1)
│ %7 = Core.apply_type(Main.Val, b)::Type{Val{_A}} where _A
│ %8 = (%7)()::Val{_A} where _A
│ %9 = Main.f1(x2, 3, %8)::Diagonal{Int64,Array{Int64,1}}
│ Base.setindex!(x, %9, 2)
│ Main.BlockDiagonal(x)
└── Core.Compiler.Const(:(return %11), false)

```

But when I add one more function…

```julia
using LinearAlgebra, BlockDiagonals
function f1(x::Vector{T}, ::Int, ::Val{:A}) where T
    Diagonal(x)
end
function f1(x::Vector{T}, i::Int, ::Val{:B}) where T
    Diagonal(x .* i)
end
function f1(x::Vector{T}, ::Int, ::Val{:C}) where T
    Diagonal(x)
end
function f1(x::Vector{T}, ::Int, ::Val{:D}) where T
    Diagonal(x)
end
function f1(x::Vector{T}, ::Int, ::Val{:E}) where T
    Diagonal(x)
end
function f2(x1, x2, a, b)
    x = Vector{Matrix}(undef, 2)
    x[1] = f1(x1, 2, Val{a}())
    x[2] = f1(x2, 3, Val{b}())
    BlockDiagonal(x)
end
@code_warntype f2([1,2,3], [2,3,4], :A, :B)

```

I nave this: Main.f1(x2, 3, %8)::Any

```julia
Variables
  #self#::Core.Compiler.Const(f2, false)
  x1::Array{Int64,1}
  x2::Array{Int64,1}
  a::Symbol
  b::Symbol
  x::Array{Array{T,2} where T,1}

Body::Union{}
1 ─ %1 = Core.apply_type(Main.Vector, Main.Matrix)::Core.Compiler.Const(Array{Array{T,2} where T,1}, false)
│ (x = (%1)(Main.undef, 2))
│ %3 = Core.apply_type(Main.Val, a)::Type{Val{_A}} where _A
│ %4 = (%3)()::Val{_A} where _A
│ %5 = Main.f1(x1, 2, %4)::Any
│ Base.setindex!(x, %5, 1)
│ %7 = Core.apply_type(Main.Val, b)::Type{Val{_A}} where _A
│ %8 = (%7)()::Val{_A} where _A
│ %9 = Main.f1(x2, 3, %8)::Any
│ Base.setindex!(x, %9, 2)
│ Main.BlockDiagonal(x)
└── Core.Compiler.Const(:(return %11), false)

```

How I can make type stable code with dispatch by Val() and more than 4 functions?

---

<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: [October 10, 2020, 12:22am UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/2 "2020-10-10T00:22:11Z")

</div>

Why do you want to use dispatch for this? This is a classic abuse of dispatch, i.e. construct type based on runtime value. You should just use a branch instead.

---

<div class="post-metadata">

### Author: ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)
#### Post date: [October 10, 2020, 12:38am UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/3 "2020-10-10T00:38:38Z")

</div>

Hello!  
I want to apply different functions based on variable value. I think, that Val() is an instrument for this.

But this is not main quastion. @code\_warntype for 4 functions give that: `Main.f1(x2, 3, %8)::Diagonal{Int64,Array{Int64,1}}` but for 5 give me that: `Main.f1(x2, 3, %8)::Any`. Why?

---

<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: [October 10, 2020, 12:56am UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/4 "2020-10-10T00:56:29Z")

</div>

> [@PharmCat](#):
>
> I think, that Val() is an instrument for this.

No it’s not. Branch is.

> [@PharmCat](#):
>
> But this is not main quastion.

But it is the main question. There are limitations in inference for cases like this since it’s not meant (and also impossible) to handle calling arbitrary function using runtime constructed types. You’ve also basically already lost when you wrote `Val{a}()`.

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [October 10, 2020, 1:01am UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/5 "2020-10-10T01:01:15Z")

</div>

> [@PharmCat](#):
>
> But this is not main quastion. @code\_warntype for 4 functions give that: `Main.f1(x2, 3, %8)::Diagonal{Int64,Array{Int64,1}}` but for 5 give me that: `Main.f1(x2, 3, %8)::Any` . Why?

The blog post on [invalidations](https://julialang.org/blog/2020/08/invalidations/) also explains what is going on here. Basically, you’re hitting a limit on inference.

I second the recommendation to use branches (`if`/`elseif`/`else`) whenever behavior depends on runtime values.

---

<div class="post-metadata">

### Author: ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)
#### Post date: [October 10, 2020, 2:20pm UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/6 "2020-10-10T14:20:47Z")

</div>

Thanks all!

So I should use `if/elseif/else` for this to avoid invalidations.

But it is very attractive to use dispatch. Because I can just make a new method and it will work. And I don’t need to rewrite `if/elseif/else` tree. Is it really no case to do dispatch by value and without invalidations?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [October 10, 2020, 2:26pm UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/7 "2020-10-10T14:26:46Z")

</div>

This is not about invalidations, just that the blogpost about it describes this phenomena.

---

<div class="post-metadata">

### Author: ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)
#### Post date: [October 11, 2020, 10:35am UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/8 "2020-10-11T10:35:59Z")

</div>

To be clear, you _can_ use Julia dynamically like this, and it can be fun and useful in some cases. It just won’t be super fast. But the main problem is not really that, I think. It is the missed opportunity to learn how to get the best out of Julia, to write really Julian code, which can take quite a while.

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [October 11, 2020, 1:13pm UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/9 "2020-10-11T13:13:15Z")

</div>

I would only recommend using dispatch here if:

1. You need/want to allow users to provide new implementations of `f1` for their own `Val` types. And allowing them to pass function instead is, for some reason, a worse solution.
2. You can use convert or function barriers to reduce the effect of the type instability over the functions that call `f1`.
3. If you think the users will add methods for `f1`, be aware this may lead to invalidations which, depending on the case, may be better or worse than taking a function parameter and disabling specialization on it.

---

<div class="post-metadata">

### Author: ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)
#### Post date: [October 12, 2020, 5:19pm UTC](https://discourse.julialang.org/t/unstable-type-with-dispatch-by-val-x-with-5-functions/48072/10 "2020-10-12T17:19:10Z")

</div>

@pablosanjose , @Henrique_Becker and all, thanks for the clarification. The main goal for dynamic style was an easy way to add user-specific methods. And I think that I will use `if/elseif/else` tree. Multiple dispatches seem a very easy but not optimal solution.
