“Only a handful” seems like a gross exaggeration, though perhaps you have large hands. If we return to your proposed criteria, being whether someone can think of a reasonable use for an API, then here are the parts of Sequence
that I had no trouble thinking of a use for during a quick scan of the documentation:
// Creating an Iterator
func makeIterator() // and use in for-in loops
// Finding Elements
func contains(Self.Element)
func contains(where: (Self.Element) -> Bool)
func first(where: (Self.Element) -> Bool)
func min()
func min(by: (Self.Element, Self.Element) -> Bool)
func max()
func max(by: (Self.Element, Self.Element) -> Bool)
// Selecting Elements
func filter((Self.Element) -> Bool)
func prefix(Int)
func suffix(Int)
// Excluding Elements
func dropFirst()
func dropFirst(Int)
func dropLast()
func dropLast(Int)
// Transforming a Sequence
func map<T>((Self.Element) -> T)
func compactMap<ElementOfResult>((Self.Element) -> ElementOfResult?)
func flatMap<SegmentOfResult>((Self.Element) -> SegmentOfResult)
func reduce<Result>(Result, (Result, Self.Element) -> Result)
func reduce<Result>(into: Result, (inout Result, Self.Element) -> ())
var lazy: LazySequence<Self>
// Iterating Over a Sequence's Elements
func forEach((Self.Element) -> Void)
var underestimatedCount: Int
// Sorting Elements
func sorted()
func sorted(by: (Self.Element, Self.Element) -> Bool)
// Splitting and Joining Elements
func joined()
func joined(separator: String)
func joined<Separator>(separator: Separator)
and here are the ones I couldn't immediately think of a use for (though perhaps someone else could):
func prefix(while: (Self.Element) -> Bool)
func drop(while: (Self.Element) -> Bool)
func enumerated()
func reversed()
func split(separator: Self.Element, maxSplits: Int, omittingEmptySubsequences: Bool)
func split(maxSplits: Int, omittingEmptySubsequences: Bool, whereSeparator: (Self.Element) -> Bool)
func elementsEqual<OtherSequence>(OtherSequence)
func elementsEqual<OtherSequence>(OtherSequence, by: (Self.Element, OtherSequence.Element) -> Bool)
func starts<PossiblePrefix>(with: PossiblePrefix)
func starts<PossiblePrefix>(with: PossiblePrefix, by: (Self.Element, Self.Element) -> Bool)
func lexicographicallyPrecedes<OtherSequence>(OtherSequence)
func lexicographicallyPrecedes<OtherSequence>(OtherSequence, by: (Self.Element, Self.Element) -> Bool)
of which elementsEqual
is the only one that seems obviously harmful to me, and the only one that I've seen evidence of harm.
I've posted many reasons why it may not be desirable, useful or worthwhile, and I'm starting to feel like they've been mostly ignored. Primarily, I've said I'm sympathetic to the view that the Sequence
and Collection
conformances should have been tucked away in a view on Set
and Dictionary
, but I don't really understand the desire to split the protocol hierarchy, leaving much of the order-dependent functionality (e.g. for-in
loops) available on Set
and Dictionary
, while removing others. If someone thinks of a type with a different useful/useless divide to the one that I've posted above, should Sequence
be split into 4 different protocols?
The rich history of String
-as-Collection
in Swift shows that even the violation of semantics/reasonable expectations may not be sufficient to split the protocol hierarchy. String even had a quarantined Collection
of characters view that has parallels to a possible solution here. Pragmatism won out in that case, because it was considered too onerous to write .characters
everywhere, even though generic algorithms can now break badly on some String
s. The situation here seems a lot less serious than that to me, since I don't believe Set
or Dictionary
violate any semantics/reasonable expectations of Sequence
or Collection
, and I can't think of any generic algorithm that would break badly when given one (though everyone accepts that you may write an algorithm that is not particular useful).