# Dispatch on constrained value type parameters

**URL:** <https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349>\
**Category:** General Usage\
**Created:** [December 5, 2018, 10:05pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349 "2018-12-05T22:05:54Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![vlc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vlc/32/4705_2.png) [@vlc](https://discourse.julialang.org/u/vlc)\
**Post date:** [December 5, 2018, 10:05pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/1 "2018-12-05T22:05:54Z")

</div>

Hello,

I’m working with `AbstractArray`s, and I would like to execute a method `foo` that takes two `AbstractArray`s when the number of dimensions of the first arrays is twice that of the first’s. An error should be thrown otherwise.

The only way I could achieve this is with `@eval` but with a finite number of dimensions. A MWE follows.

```julia
const ndimmax = 10

for n in 1:ndimmax
    @eval foo(::AbstractArray{S, $(2n)}, ::AbstractArray{T, $n}) where {S, T} = println("do something...")
end

```

This does the job as long as the number of dimensions remains small:

```julia
julia> foo(rand(10, 10), rand(10))
do something...

```

However I was wondering if there is another way I could achieve this ? It wouldn’t make sense to use `@generated` functions since the value type parameters would be outside the quote…

Thanks!

V.

---

<div class="post-metadata">

**Author:** ![datnamer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datnamer/32/3471_2.png) [@datnamer](https://discourse.julialang.org/u/datnamer)\
**Post date:** [December 5, 2018, 10:11pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/2 "2018-12-05T22:11:09Z")

</div>

Wouldn’t this require an esoteric language with dependent typing like idris

---

<div class="post-metadata">

**Author:** ![vlc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vlc/32/4705_2.png) [@vlc](https://discourse.julialang.org/u/vlc)\
**Post date:** [December 5, 2018, 10:22pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/3 "2018-12-05T22:22:52Z")

</div>

Hi,

I wasn’t even aware there were languages that were doing this… Thanks for the tip!

This isn’t much of a limitation (in my case, the type parameter `N` refers to the dimension of a multi-index, which will not exceed 4), but I’ve been scratching my head on this and was wondering whether there already existed a way to do this in julia…

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 5, 2018, 10:38pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/4 "2018-12-05T22:38:21Z")

</div>

No, this isn’t something you can easily express through dispatch. If all you want to do is throw am error if the condition is not met, I would suggest doing exactly that: check the condition at run time and throw an error if it fails.

If the runtime check is too expensive or if you really need to dispatch to some other method if your condition doesn’t hold, then it might be possible to express what you want with a combination of traits and `@pure` abuse, but I wouldn’t suggest going down that road unless it’s necessary.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 5, 2018, 10:51pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/5 "2018-12-05T22:51:27Z")

</div>

Just for fun, here’s a demonstration of how you might do this with traits. I had assumed that `Base.@pure` would be necessary, but it seems that it’s not (Julia 1.0 is much better at this sort of thing):

```julia
"""
Public-facing method, which checks our condition on N1 and N2 and 
then calls the _foo() method containing the actual implementation.
"""
function foo(x1::AbstractArray{T1, N1}, x2::AbstractArray{T2, N2}) where {T1, T2, N1, N2}
    _foo(is_ok(N1, N2), x1, x2)
end

"""
Returns Val{true}() if N1 == 2 * N2, Val{false}() otherwise.

This looks type-unstable, but Julia's constant propagation seems
to allow it to infer the result when N1 and N2 are constants
"""
is_ok(N1, N2) = Val(N1 == 2 * N2)

_foo(::Val{true}, x1, x2) = x1
_foo(::Val{false}, x1, x2) = error("x1 should have twice as many dimensions as x2")

```

```julia
julia> foo(zeros(2, 2), zeros(2))
2×2 Array{Float64,2}:
 0.0 0.0
 0.0 0.0

julia> foo(zeros(2, 2, 2), zeros(2))
ERROR: x1 should have twice as many dimensions as x2
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] _foo(::Val{false}, ::Array{Float64,3}, ::Array{Float64,1}) at ./REPL[4]:1
 [3] foo(::Array{Float64,3}, ::Array{Float64,1}) at ./REPL[1]:6
 [4] top-level scope at none:0

```

Through the magic of constant propagation, this is even type-stable:

```julia
julia> @code_warntype foo(zeros(2, 2), zeros(2))
Body::Array{Float64,2}
6 1 ─ return x1  

```

---

<div class="post-metadata">

**Author:** ![datnamer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datnamer/32/3471_2.png) [@datnamer](https://discourse.julialang.org/u/datnamer)\
**Post date:** [December 5, 2018, 11:03pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/6 "2018-12-05T23:03:21Z")

</div>

That’s amazing.

---

<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:** [December 5, 2018, 11:18pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/7 "2018-12-05T23:18:55Z")

</div>

Why `Val` wrap everything?

```julia
function foo(x1::AbstractArray{T1, N1}, x2::AbstractArray{T2, N2}) where {T1, T2, N1, N2}
    _foo(is_ok(N1, N2), x1, x2)
end
is_ok(N1, N2) = N1 == 2 * N2
_foo(v, x1, x2) = v ? x1 : error("x1 should have twice as many dimensions as x2")

```

```julia
julia> @code_warntype foo(zeros(2, 2), zeros(2))
Body::Array{Float64,2}
2 1 ─ return x1  

```

works just as well.

---

<div class="post-metadata">

**Author:** ![vlc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vlc/32/4705_2.png) [@vlc](https://discourse.julialang.org/u/vlc)\
**Post date:** [December 6, 2018, 6:08am UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/8 "2018-12-06T06:08:38Z")

</div>

Thanks for the input, along the line of @rdeits’s solution:

```julia
 @generated function bar(::AbstractArray{S, N}, ::AbstractArray{T, M}) where {S, N, T, M}
    if N == 2M
        :(println("do something..."))
    else
        :(error("ndims(x) != ndims(y)"))
    end
end

```

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [December 6, 2018, 8:15pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/9 "2018-12-06T20:15:30Z")

</div>

Would this be just as efficient?

```julia
function foo(x1::AbstractArray{T1, N1}, x2::AbstractArray{T2, N2}) where {T1, T2, N1, N2}
    N1 == 2*N2 || error("x1 should have twice as many dimensions as x2")
    return x1
end

```

If so it seems simpler, avoiding intermediate `_foo` trait or using a generated function.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 6, 2018, 8:42pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/10 "2018-12-06T20:42:54Z")

</div>

Yeah, that’s what I was alluding to in my first post. It’s clear, efficient, and super simple. The trait stuff is only useful if you want to do something like dispatch to different methods based on some condition.

---

<div class="post-metadata">

**Author:** ![datnamer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datnamer/32/3471_2.png) [@datnamer](https://discourse.julialang.org/u/datnamer)\
**Post date:** [December 6, 2018, 9:24pm UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/11 "2018-12-06T21:24:53Z")

</div>

So that calculation happens at compile time? How far can you go with calculated traits like that?

---

<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 7, 2018, 6:58am UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/12 "2018-12-07T06:58:03Z")

</div>

> [@datnamer](#):
>
> How far can you go with calculated traits like that?

There should be no theoretical limitation, but if you go overboard with doing calculations using types you pay in compilation time. It is best to benchmark particular cases.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [December 7, 2018, 9:24am UTC](https://discourse.julialang.org/t/dispatch-on-constrained-value-type-parameters/18349/13 "2018-12-07T09:24:12Z")

</div>

No traits, but I like @andyferris’s [A practical introduction to metaprogramming in Julia](https://github.com/FugroRoames/RoamesNotebooks/blob/master/A%20practical%20introduction%20to%20metaprogramming%20in%20Julia.ipynb), where he demonstrates ([video](https://youtu.be/SeqAQHKLNj4?t=3963)) in the section “Multiple dispatch as a metaprogramming technique” that Julia’s type system is Turing complete.
