How to dispatch on an iterable (e.g. accept both tuple or array)

Is it possible to dispatch on if a method argument is iterable? I’d like to dispatch a method based on if an argument is scalar input or some kind of iterable. My main target for the iterable method is to accept either an Array or a Tuple. Is that possible? Or do I need to use traits for this?

Looks like some discussion on this already occurred:

https://github.com/JuliaLang/julia/issues/34535

https://github.com/JuliaLang/julia/issues/23429

And SimpleTraits has an IsIterator trait https://github.com/mauro3/SimpleTraits.jl

The SimpleTraits.jl solution fails because numbers are iterable:

using SimpleTraits
using SimpleTraits.BaseTraits

@traitfn f(x::T) where {T; IsIterator{T}} = "iterable"
@traitfn f(x::T) where {T; !IsIterator{T}} = "not iterable"

I get

julia> f((1,2))
"iterable"

julia> f([1,2])
"iterable"

julia> struct A
       end

julia> f(A)
"not iterable"

which looks great, but then

julia> f(1.0)
"iterable"

I don’t think this is feasible. In a lot of code foo(itr::Any) is the “Any” method, so iteration is the default and then <: Number is used for other things.

Not ideal, I guess. But you have to hope package authors appropriately sub-typed the types they made.

1 Like

It turns out that SimpleTraits.jl can in fact solve this. See the reply to my issue: https://github.com/mauro3/SimpleTraits.jl/issues/66#issuecomment-614289415

1 Like