I think the general idea seems useful, but the proposed versions seem kind of hard to use due to the 3-tuple return combined with optional types. The usage examples you give mostly just test these for optionality, and they all ignore the prefix count. I also notice that the C++ version returns the pair of iterators, making it easier to pick up from where you left off, a use case that you might want to consider. In general I would be interested in seeing more use cases and alternative implementations.
I don't have time right now to think a lot about this, but one possibility would be something like zip(_:_:)
, returning a (lazy?) sequence type that provided this information in some form. e.g. return a sequence of enum cases roughly like .equal(_.SubSequence)
, .notEqual(Element, Element)
, .firstSuffix(S1.SubSequence)
, .secondSuffix(S2.SubSequence)
, but with better names and more thought about the performance requirements and details (e.g. should .notEqual
provide elements or equal length subsequences where they differ?).
divergence([2, 3, 4, 5], [2, 3, 5, 7, 11])
// roughly [.equal([2, 3]), .notEqual(4, 5), .notEqual(5, 7), .secondSuffix([11])]
// or [.equal([2, 3]), .notEqual([4, 5], [5, 7]), .secondSuffix([11])]
Or if that is too general and almost all the use cases really only need the length of the common prefix and the differing elements, you could consider returning a struct with the common prefix length and an enum with a case containing the differing pair of (non-optional) elements and other cases describing the other possibilities (sequences are the same, hit the end of one sequence or the other).