mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
248 lines
8.3 KiB
Swift
248 lines
8.3 KiB
Swift
//===--- SetAlgebra.swift - Protocols for set operations ------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
//
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// A generalized set whose distinct elements are not necessarily
|
|
/// disjoint.
|
|
///
|
|
/// In a model of `SetAlgebra`, some elements may subsume other
|
|
/// elements, where
|
|
///
|
|
/// > `a` **subsumes** `b` iff `([a] as Self).isSupersetOf([b])`
|
|
///
|
|
/// In many models of `SetAlgebra` such as `Set<Element>`, `a`
|
|
/// *subsumes* `b` if and only if `a == b`, but that is not always the
|
|
/// case. For example, option sets typically do not satisfy that
|
|
/// property.
|
|
///
|
|
/// Two elements are **disjoint** when neither one *subsumes* the other.
|
|
///
|
|
/// - SeeAlso: `OptionSet`.
|
|
///
|
|
/// - Axioms, where `S` conforms to `SetAlgebra`, `x` and `y` are
|
|
/// of type `S`, and `e` is of type `S.Element`:
|
|
///
|
|
/// - `S() == []`
|
|
/// - `x.intersect(x) == x`
|
|
/// - `x.intersect([]) == []`
|
|
/// - `x.union(x) == x`
|
|
/// - `x.union([]) == x`
|
|
/// - `x.contains(e)` implies `x.union(y).contains(e)`
|
|
/// - `x.union(y).contains(e)` implies `x.contains(e) || y.contains(e)`
|
|
/// - `x.contains(e) && y.contains(e)` iff `x.intersect(y).contains(e)`
|
|
/// - `x.isSubsetOf(y)` iff `y.isSupersetOf(x)`
|
|
/// - `x.isStrictSupersetOf(y)` iff `x.isSupersetOf(y) && x != y`
|
|
/// - `x.isStrictSubsetOf(y)` iff `x.isSubsetOf(y) && x != y`
|
|
public protocol SetAlgebra : Equatable, ArrayLiteralConvertible {
|
|
/// A type for which `Self` provides a containment test.
|
|
associatedtype Element
|
|
|
|
/// Creates an empty set.
|
|
///
|
|
/// - Equivalent to `[] as Self`
|
|
init()
|
|
|
|
/// Returns `true` if `self` contains `member`.
|
|
///
|
|
/// - Equivalent to `self.intersect([member]) == [member]`
|
|
@warn_unused_result
|
|
func contains(member: Element) -> Bool
|
|
|
|
/// Returns the set of elements contained in `self`, in `other`, or in
|
|
/// both `self` and `other`.
|
|
@warn_unused_result
|
|
func union(other: Self) -> Self
|
|
|
|
/// Returns the set of elements contained in both `self` and `other`.
|
|
@warn_unused_result
|
|
func intersect(other: Self) -> Self
|
|
|
|
/// Returns the set of elements contained in `self` or in `other`,
|
|
/// but not in both `self` and `other`.
|
|
@warn_unused_result
|
|
func exclusiveOr(other: Self) -> Self
|
|
|
|
/// If `member` is not already contained in `self`, inserts it.
|
|
///
|
|
/// - Equivalent to `self.unionInPlace([member])`
|
|
/// - Postcondition: `self.contains(member)`
|
|
mutating func insert(member: Element)
|
|
|
|
/// If `member` is contained in `self`, removes and returns it.
|
|
/// Otherwise, removes all elements subsumed by `member` and returns
|
|
/// `nil`.
|
|
///
|
|
/// - Postcondition: `self.intersect([member]).isEmpty`
|
|
mutating func remove(member: Element) -> Element?
|
|
|
|
/// Insert all elements of `other` into `self`.
|
|
///
|
|
/// - Equivalent to replacing `self` with `self.union(other)`.
|
|
/// - Postcondition: `self.isSupersetOf(other)`
|
|
mutating func unionInPlace(other: Self)
|
|
|
|
/// Removes all elements of `self` that are not also present in
|
|
/// `other`.
|
|
///
|
|
/// - Equivalent to replacing `self` with `self.intersect(other)`
|
|
/// - Postcondition: `self.isSubsetOf(other)`
|
|
mutating func intersectInPlace(other: Self)
|
|
|
|
/// Replaces `self` with a set containing all elements contained in
|
|
/// either `self` or `other`, but not both.
|
|
///
|
|
/// - Equivalent to replacing `self` with `self.exclusiveOr(other)`
|
|
mutating func exclusiveOrInPlace(other: Self)
|
|
|
|
//===--- Requirements with default implementations ----------------------===//
|
|
/// Returns the set of elements contained in `self` but not in `other`.
|
|
@warn_unused_result
|
|
func subtract(other: Self) -> Self
|
|
|
|
/// Returns `true` iff every element of `self` is contained in `other`.
|
|
@warn_unused_result
|
|
func isSubsetOf(other: Self) -> Bool
|
|
|
|
/// Returns `true` iff `self.intersect(other).isEmpty`.
|
|
@warn_unused_result
|
|
func isDisjointWith(other: Self) -> Bool
|
|
|
|
/// Returns `true` iff every element of `other` is contained in `self`.
|
|
@warn_unused_result
|
|
func isSupersetOf(other: Self) -> Bool
|
|
|
|
/// Returns `true` iff `self.contains(e)` is `false` for all `e`.
|
|
var isEmpty: Bool { get }
|
|
|
|
/// Creates the set containing all elements of `sequence`.
|
|
init<S : Sequence where S.Iterator.Element == Element>(_ sequence: S)
|
|
|
|
/// Removes all elements of `other` from `self`.
|
|
///
|
|
/// - Equivalent to replacing `self` with `self.subtract(other)`.
|
|
mutating func subtractInPlace(other: Self)
|
|
|
|
/// Returns `true` iff `a` subsumes `b`.
|
|
///
|
|
/// - Equivalent to `([a] as Self).isSupersetOf([b])`
|
|
@warn_unused_result
|
|
static func element(a: Element, subsumes b: Element) -> Bool
|
|
|
|
/// Returns `true` iff `a` is disjoint with `b`.
|
|
///
|
|
/// Two elements are disjoint when neither one subsumes the other.
|
|
///
|
|
/// - SeeAlso: `Self.element(_, subsumes:_)`
|
|
@warn_unused_result
|
|
static func element(a: Element, isDisjointWith b: Element) -> Bool
|
|
}
|
|
|
|
/// `SetAlgebra` requirements for which default implementations
|
|
/// are supplied.
|
|
///
|
|
/// - Note: A type conforming to `SetAlgebra` can implement any of
|
|
/// these initializers or methods, and those implementations will be
|
|
/// used in lieu of these defaults.
|
|
extension SetAlgebra {
|
|
/// Creates the set containing all elements of `sequence`.
|
|
public init<
|
|
S : Sequence where S.Iterator.Element == Element
|
|
>(_ sequence: S) {
|
|
self.init()
|
|
for e in sequence { insert(e) }
|
|
}
|
|
|
|
/// Creates a set containing all elements of the given `arrayLiteral`.
|
|
///
|
|
/// This initializer allows an array literal containing
|
|
/// `Self.Element` to represent an instance of the set, wherever it
|
|
/// is implied by the type context.
|
|
public init(arrayLiteral: Element...) {
|
|
self.init(arrayLiteral)
|
|
}
|
|
|
|
/// Removes all elements of `other` from `self`.
|
|
///
|
|
/// - Equivalent to replacing `self` with `self.subtract(other)`.
|
|
public mutating func subtractInPlace(other: Self) {
|
|
self.intersectInPlace(self.exclusiveOr(other))
|
|
}
|
|
|
|
/// Returns `true` iff every element of `self` is contained in `other`.
|
|
@warn_unused_result
|
|
public func isSubsetOf(other: Self) -> Bool {
|
|
return self.intersect(other) == self
|
|
}
|
|
|
|
/// Returns `true` iff every element of `other` is contained in `self`.
|
|
@warn_unused_result
|
|
public func isSupersetOf(other: Self) -> Bool {
|
|
return other.isSubsetOf(self)
|
|
}
|
|
|
|
/// Returns `true` iff `self.intersect(other).isEmpty`.
|
|
@warn_unused_result
|
|
public func isDisjointWith(other: Self) -> Bool {
|
|
return self.intersect(other).isEmpty
|
|
}
|
|
|
|
/// Returns the set of elements contained in `self` but not in `other`.
|
|
@warn_unused_result
|
|
public func subtract(other: Self) -> Self {
|
|
return self.intersect(self.exclusiveOr(other))
|
|
}
|
|
|
|
/// Returns `true` iff `self.contains(e)` is `false` for all `e`.
|
|
public var isEmpty: Bool {
|
|
return self == Self()
|
|
}
|
|
|
|
/// Returns `true` iff every element of `other` is contained in `self`
|
|
/// and `self` contains an element that is not contained in `other`.
|
|
@warn_unused_result
|
|
public func isStrictSupersetOf(other: Self) -> Bool {
|
|
return self.isSupersetOf(other) && self != other
|
|
}
|
|
|
|
/// Returns `true` iff every element of `self` is contained in `other`
|
|
/// and `other` contains an element that is not contained in `self`.
|
|
@warn_unused_result
|
|
public func isStrictSubsetOf(other: Self) -> Bool {
|
|
return other.isStrictSupersetOf(self)
|
|
}
|
|
|
|
/// Returns `true` iff `a` subsumes `b`.
|
|
///
|
|
/// - Equivalent to `([a] as Self).isSupersetOf([b])`
|
|
@warn_unused_result
|
|
public static func element(a: Element, subsumes b: Element) -> Bool {
|
|
return ([a] as Self).isSupersetOf([b])
|
|
}
|
|
|
|
/// Returns `true` iff `a` is disjoint with `b`.
|
|
///
|
|
/// Two elements are disjoint when neither one subsumes the other.
|
|
///
|
|
/// - SeeAlso: `Self.element(_, subsumes:_)`
|
|
@warn_unused_result
|
|
public static func element(a: Element, isDisjointWith b: Element) -> Bool {
|
|
return ([a] as Self).isDisjointWith([b])
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable, renamed="SetAlgebra")
|
|
public typealias SetAlgebraType = SetAlgebra
|
|
|