Multiple Dispatch?

Continuing the discussion from Instance-level polymorphism:

I've been writing a versions of C++'s functions that work on already sorted sequences, like std::merge. My code is an extension on Sequence, so one of the operands is the receiver and the other is the first argument. The functionality is symmetric, so it would be nice if we could express it that way.

Then I remembered that I read about something called multi-methods. I realized that our tuple syntax could provide a way to describe co-equal receivers:

extension (Sequence, Sequence) where .0.Element == .1.Element {
    public func mergeSorted<T>(as type: T.Type, by areInIncreasingOrder: (.0.Element, .1.Element) throws -> Bool) rethrows -> T where T: RangeReplaceableCollection, T.Element == .0.Element
}

I want to specify that at least one of the tuple-d parameters cannot be Any. It isn't limited to two; three and above are supported, as well as generics when/if that's added. I don't if we should allow types, or only just protocols, protocol combinations, non-final classes, and class & protocol combinations. I hope that it's possible to add dynamic dispatch; either we attach the dispatch table to one of the types/classes/protocols, or we make a new dispatch table type. Since the syntax is basically slapping methods on tuples, maybe they can go onto a witness table for the corresponding tuple. In my example above, Sequence can't be used as a variable's type since it has Self and associated-type requirements, so maybe we need to wait until we generalize protocol-based variables for PAT-enabled protocols.

We should be able to have (Sequence, Collection), (Collection, Collection), etc. overrides as needed.

(In the initial post suggestions, I found out I already ranted about this a long time ago. I come up with ideas so often they push already posted ones out of my immediate memory. Hopefully, this post is a reason to add multiple dispatch.)

1 Like