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 would have expect this to behave identical to Set.isSuperset(of:)
:
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
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
}
What this means is that a collection can check if it contains another collection. I think this was introduced along with the regex features, mainly to check if a String
contains a given substring.
Note that this works for an Array
as expected:
let a: Array = [1, 2, 3]
a.contains([1]) // true
a.contains([1, 2]) // true
a.contains([1, 2, 3]) // true
a.contains([1, 2, 3, 4]) // false
But as mentioned above, this surprisingly does not work for Set
if the passed in collection contains more than one element.
I think I understand where the issue lies on a technical level, but I find this behavior highly confusing from a Swift user’s perspective and we actually ran into this situation in our code base.
Should I file an issue for this on GitHub - swiftlang/swift: The Swift Programming Language?