Syntactic sugar for dispatch on a single type parameter

I have some code using traits, where I want to dispatch on a specific type parameter of a function argument. Is there a shortcut for omitting the other parameters, if the one I want to dispatch on is not the first parameter?

For definiteness, consider an example of a type with three parameters:

struct mystruct{T1,T2,T3}
end

If I want to dispatch on the last parameter I have to write either something like

test(::mystruct{<:Any,<:Any,<:Nothing}) = true
test(::mystruct{<:Any,<:Any,<:Any}) = false

or

test(::mystruct{T1,T2,T3}) where {T1,T2,T3<:Nothing} = true
test(::mystruct{T1,T2,T3}) where {T1,T2,T3} = false

In the actual code there are more than just three type parameters, hence it would be convenient not having to spell out all parameters, e.g., something like

test(::mystruct{,,<:Nothing}) = true
test(::mystruct{,,<:Any}) = false
1 Like

Sort of — define an alias that changes the order. Eg

struct Foo{A,B} end
const Bar{B,A} = Foo{A,B}
Foo{Int,Float64}() isa Bar{Float64}
1 Like

This one has a shorter spelling:

test(::MyStruct) = false

No need to write the parameters.

Also, remember that type names should be CapitalCase.

Neat idea, thanks.

If you always dispatch on the same parameter, place it first?

You can also write a helper function like this:

julia> struct mystruct{T1,T2,T3}
       end

julia> mystruct_type(;A=Any,B=Any,C=Any) = mystruct{<:A,<:B,<:C}
mystruct_type (generic function with 1 method)

julia> mystruct_type(B=Nothing)
mystruct{var"#s6",var"#s5",var"#s4"} where var"#s4" where var"#s5"<:Nothing where var"#s6"

julia> f(::mystruct_type(B=Nothing)) = "NoB"
f (generic function with 1 method)

julia> f(::mystruct_type(A=Nothing)) = "NoA"
f (generic function with 2 methods)

julia> f(mystruct{Nothing, Int, Int}())
"NoA"

julia> f(mystruct{Int, Nothing, Int}())
"NoB"
3 Likes

You could image writing a macro to allow that, although that exact thing is a syntax error so it won’t work. In a similar spirit, at one point I did write a macro which expands to <:Any, which is at least its fewer characters, e.g.

@∷ test(::mystruct{∷,∷,<:Nothing}) = true

Plus I kind of liked the symmetry with array slicing, like mystruct{∷,∷,Int} and myarray[:,:,1] which have similar abstract meanings. You could try it, although tbh, I ultimately I hated the look of having to call the macro and didn’t like the extra obfuscation, so I stopped doing it.

That’s unfortunately not the case. Otherwise, yes, that would be the obvious thing to do.

1 Like

Thanks a lot. That’s a pretty neat suggestion as well!

I totally agree. This looks pretty cute, but it adds a level of obfuscation, which is probably better avoided. Thanks nonetheless for the suggestion!