There's no ends(with:) counterpart to starts(with:)

So I made one: Add `ends(with:)` by amomchilov · Pull Request #224 · apple/swift-algorithms · GitHub. Would love some feedback!

For comparison, there's Sequence.starts(with:).

This seems like an odd omission from the standard library. It could be useful for implementing something like String.hasSuffix, which is currently implemented in terms of starts(with:):

6 Likes

As for the implementation questions, I would note that you can now dynamically downcast to, say, BidirectionalCollection or RandomAccessCollection. So you can have multiple implementation strategies behind a single interface:

func doTest() -> Int {
    test(["a"])
}

// ---------------------

func test<S>(_ x: S) -> Int where S: Sequence, S.Element: StringProtocol {
    if let c = x as? any Collection<S.Element> {
        return _test(c)
    }
    return _test(x)
}

func _test<S>(_ x: S) -> Int where S: Sequence, S.Element: StringProtocol {
  99
}

func _test<C>(_ x: C) -> Int where C: Collection, C.Element: StringProtocol {
  42
}

The result of calling doTest is 42, indicating that Array was recognised as a Collection, instead of just being any old Sequence.

Of course, this needs to be balanced against the cost of the downcast itself, but since you really want specialisation for generics anyway, in many cases it will be statically known that a type can benefit from the fast path. Due to retroactive conformances, we can't statically rule out fast paths (so I'd advise not having too many), but we can statically rule them in.

Unfortunately, since this is a relatively new capability in the language, the optimiser doesn't currently handle it very well: Optimiser fails to devirtualise cast to existential followed by immediate unboxing · Issue #62264 · apple/swift · GitHub

3 Likes

Woah this is really neat!

Do you think I should do it, with the implicit assumption that the optimizations will be improved in this area? Or should I just keep it the more straight-forward implementation that faster today, and further improve it in the future if necessary?