Description
Motivation
There is a confusing behavior of Set.contains(_:)
when passing a collection that contains more than one element:
let s: Set = [1, 2, 3]
s.contains([1]) // true
s.contains([1] as Set) // true
s.contains([1, 2]) // false 🤨
s.contains([1, 2] as Set) // false 🤨
s.contains([1, 2, 3]) // false 🤨
s.contains([1, 2, 3] as Set) // false 🤨
I think this confusion is introduced by a Collection
extension in the _StringProcessing
module:
extension Collection where Self.Element : Equatable {
/// Returns a Boolean value indicating whether the collection contains the
/// given sequence.
/// - Parameter other: A sequence to search for within this collection.
/// - Returns: `true` if the collection contains the specified sequence,
/// otherwise `false`.
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
public func contains<C>(_ other: C) -> Bool where C : Collection, Self.Element == C.Element
}
I understand that this behavior is caused by the Set
internally storing its elements in a random order (as viewed from outside), so checking whether “[…] the collection contains the given sequence” is not really a useful thing to do on a Set
, making this method pretty much useless there.
Proposed solution
To make this method useful on Set
, it could simply forward to Set.isSuperset(of:)
, which is what I would have expected in the first place:
s.isSuperset(of: [1, 2]) // true
s.isSuperset(of: [1, 2] as Set) // true
s.isSuperset(of: [1, 2, 3]) // true
s.isSuperset(of: [1, 2, 3] as Set) // true
While maybe not strictly correct in the sense of the documentation that “[…] the collection contains the given sequence” because the order of elements as passed is irrelevant, I think it is more useful because the behavior is at least deterministic.
Alternatives considered
None really. Do nothing and keep the behavior as-is, I guess.
Additional information
I posted on the Swift forum about this and received only one reply that agreed with the confusing behavior.
Here’s the thread: Passing a Collection to Set.contains(_:) leads to confusing results