# Syntax for dispatching on subtypes

**URL:** <https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871>\
**Category:** General Usage\
**Created:** [November 6, 2023, 3:29pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871 "2023-11-06T15:29:06Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [November 6, 2023, 3:29pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/1 "2023-11-06T15:29:06Z")

</div>

If I have a type with multiple subtypes, and I want to dispatch on one of the types I usually type:

```julia
struct Foo{A,B,...}
   ...
end

function somefunc(f::F{A, SomeSubtype,C,...}) where {A,C,...}
   ...
end

```

This becomes a bit cumbersome. Is there some better syntax?

Something like this would already be nice

```julia
function somefunc(f::F{_,SomeSubtype,_,...})
   ...
end

```

but this doesn’t work.

---

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [November 6, 2023, 3:32pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/2 "2023-11-06T15:32:04Z")

</div>

You can at least leave out all ones behind (`C,...`) and just do

```julia
function somefunc(f::F{A, SomeSubtype}) where {A}
   ...
end

```

which makes ordering of the parameters a design decision: put those you dispatch on often far upfront.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [November 6, 2023, 3:32pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/3 "2023-11-06T15:32:37Z")

</div>

You don´t need to repeat all types, just up to the one where dispatch is needed. Thus, the idea is to put first the types that are needed for dispatch. For example:

```julia
julia> struct A{T1,T2}
           x::T1
           y::T2
       end

julia> f(a::A{T1}) where {T1<:Int} = "Int"
f (generic function with 2 methods)

julia> f(a::A{T1}) where {T1<:Float64} = "Float64"
f (generic function with 2 methods)

julia> f(A(1,2))
"Int"

julia> f(A(1.0, 2))
"Float64"

```

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [November 6, 2023, 3:41pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/4 "2023-11-06T15:41:57Z")

</div>

Great, I wasn’t aware of this. Thanks a lot!

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [November 6, 2023, 4:20pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/5 "2023-11-06T16:20:17Z")

</div>

> [@f.ij](#):
>
> ```julia
> function somefunc(f::F{_,SomeSubtype,_,...})
> ...
> end
> 
> ```

I don’t think we have anything like this with `_`, but if there are parameters you want to “ignore” you can write them as `<:Any`. Like  
`F{<:Any, <:TargetSupertype, <:Any, <:AnotherType}`. Note that an inline `<:X` is a shorthand for something like `_X` with a `where {_X <: X}` at the end (although `_X` is something I made up and what the compiler uses will be sure to be unique), so those substitutions are equivalent to `F{A, B, C, D} where {A,B<:TargetSupertype,C,D<:AnotherType}`. Note also that `where A<:Any` is equivalent to `where A`, which is why I didn’t expand those fully.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [November 6, 2023, 4:51pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/6 "2023-11-06T16:51:19Z")

</div>

Ah, of course. This syntax I knew but somehow didn’t think to use. Thanks for the suggestion. Both suggestions together make everything a lot easier to write and maintain in my code. Thanks!

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [November 6, 2023, 5:31pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/7 "2023-11-06T17:31:49Z")

</div>

I wrote a macro for this once but never really used it myself (hence not registered; it also relies on Julia internals): [GitHub - fatteneder/NamedTypeParameters.jl: Macro for naming type parameters in signatures](https://github.com/fatteneder/NamedTypeParameters.jl)

With this you could ‘shorten’ it to

```julia
function somefunc(f::@parameterize(F{B=SomeSubtype}))
   ...
end

```

The macro name should be shortened too, otherwise its not much shorter 😆

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [November 7, 2023, 12:46pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/8 "2023-11-07T12:46:24Z")

</div>

Interestingly, both of the suggested solutions don’t seem to work for `Type{T}` type selectors.

If I want to dispatch on the subtype of a passed type, I do have to write out everything. Any suggestions for this?

---

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [November 7, 2023, 3:28pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/9 "2023-11-07T15:28:07Z")

</div>

Can you be a bit more specific? For example you might have ran into the warning from  
[Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#man-parametric-composite-types) ? If so see the two code blocks afterwards for the fix.

---

<div class="post-metadata">

**Author:** ![de-souza](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/de-souza/32/43417_2.png) [@de-souza](https://discourse.julialang.org/u/de-souza)\
**Post date:** [November 7, 2023, 3:34pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/10 "2023-11-07T15:34:42Z")

</div>

Is there any difference between the form

```julia
f(::AbstractType{A,B}) where {A,B} = B

```

and this form?

```julia
f(::AbstractType{<:Any,B}) where {B} = B

```

I’ve got the impression that the first one is considered more “specialized” by the compiler but don’t remember reading anything explaining the difference in the Julia docs.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [November 7, 2023, 10:30pm UTC](https://discourse.julialang.org/t/syntax-for-dispatching-on-subtypes/105871/11 "2023-11-07T22:30:51Z")

</div>

I don’t think the two methods differ:

```julia
julia> (AbstractArray{<:Any, B} where {B}) == (AbstractArray{A, B} where {A, B})
true

```

Also, when I define both in a fresh REPL session (using AbstractArray as an example type) I only get one method at the end. Seems like they are exactly the same:

```julia
julia> f(::AbstractArray{A,B}) where {A,B} = B
f (generic function with 1 method)

julia> f(::AbstractArray{<:Any,B}) where {B} = B
f (generic function with 1 method)

julia> methods(f)
# 1 method for generic function "f" from Main:
 [1] f(::AbstractArray{<:Any, B}) where B
     @ REPL[4]:1

```

But funnily enough, if I define the first method again in the same session, it changes the printout of `methods` to match the way it was defined. Perhaps because `===` is not true for both types written above.

```julia
julia> f(::AbstractArray{A,B}) where {A,B} = B
f (generic function with 1 method)

julia> methods(f)
# 1 method for generic function "f" from Main:
 [1] f(::AbstractArray{A, B}) where {A, B}
     @ REPL[6]:1

```

Unless I am missing something super subtle here, the only difference is that you cannot use the type parameter `A` directly in the function body 🤷‍♂️
