Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
373 changes: 373 additions & 0 deletions stdlib/public/core/Tuple.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,373 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

// Variadic functions for comparison operations on tuple types.

/// Returns a Boolean value indicating whether the corresponding components of
/// two tuples are equal.
///
/// For two tuples to compare as equal, each corresponding pair of components
/// must be equal. The following example compares tuples made up of 4
/// components:
///
/// let a = ("a", 1, 2, 3)
/// let b = ("a", 1, 2, 3)
/// print(a == b)
/// // Prints "true"
///
/// let c = ("a", 1, 2, 4)
/// print(a == c)
/// // Prints "false"
///
/// - Parameters:
/// - lhs: A tuple of `Equatable` elements.
/// - rhs: Another tuple of elements of the same type as `lhs`.
@_alwaysEmitIntoClient
public func ==<each B: Equatable>(lhs: (repeat each B), rhs: (repeat each B)) -> Bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aside: does the choice of B as the generic parameter name have some particular significance or prior art?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, no, this was leftover from originally writing it as <A, each B> thinking it might make the algorithm simpler. It didn’t. I’ll rename and make it more verbose!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the verbosity budget should be flush, what with all the boilerplate removal! 😄

for (lhs, rhs) in repeat (each lhs, each rhs) {
if lhs != rhs {
return false
}
}
return true
}

/// Returns a Boolean value indicating whether any corresponding components of
/// the two tuples are not equal.
///
/// For two tuples to compare as equal, each corresponding pair of components
/// must be equal. The following example compares tuples made up of 4
/// components:
///
/// let a = ("a", 1, 2, 3)
/// let b = ("a", 1, 2, 3)
/// print(a != b)
/// // Prints "false"
///
/// let c = ("a", 1, 2, 4)
/// print(a != c)
/// // Prints "true"
///
/// - Parameters:
/// - lhs: A tuple of `Equatable` elements.
/// - rhs: Another tuple of elements of the same type as `lhs`.
@_alwaysEmitIntoClient
public func !=<each B: Equatable>(lhs: (repeat each B), rhs: (repeat each B)) -> Bool {
for (lhs, rhs) in repeat (each lhs, each rhs) {
if lhs == rhs {
return false
}
}
return true
Comment on lines +64 to +70
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nicer if we forwarded to the same member-wise operations, e.g.

    guard lhs != rhs else {
      return false
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

}

/// Returns a Boolean value indicating whether the first tuple is ordered
/// before the second in a lexicographical ordering.
///
/// Given two tuples `(a1, a2, ..., aN)` and `(b1, b2, ..., bN)`, the first
/// tuple is before the second tuple if and only if
/// `a1 < b1` or (`a1 == b1` and
/// `(a2, ..., aN) < (b2, ..., bN)`).
///
/// - Parameters:
/// - lhs: A tuple of `Comparable` elements.
/// - rhs: Another tuple of elements of the same type as `lhs`.
@_alwaysEmitIntoClient
public func < <each B: Comparable>(lhs: (repeat each B), rhs: (repeat each B)) -> Bool {
for (lhs, rhs) in repeat (each lhs, each rhs) {
if lhs >= rhs {
return false
}
}
return true
}

/// Returns a Boolean value indicating whether the first tuple is ordered
/// before or the same as the second in a lexicographical ordering.
///
/// Given two tuples `(a1, a2, ..., aN)` and `(b1, b2, ..., bN)`, the first
/// tuple is before or the same as the second tuple if and only if
/// `a1 < b1` or (`a1 == b1` and
/// `(a2, ..., aN) <= (b2, ..., bN)`).
///
/// - Parameters:
/// - lhs: A tuple of `Comparable` elements.
/// - rhs: Another tuple of elements of the same type as `lhs`.
@_alwaysEmitIntoClient
public func <= <each B: Comparable>(lhs: (repeat each B), rhs: (repeat each B)) -> Bool {
for (lhs, rhs) in repeat (each lhs, each rhs) {
if lhs > rhs {
return false
}
}
return true
}

/// Returns a Boolean value indicating whether the first tuple is ordered
/// after the second in a lexicographical ordering.
///
/// Given two tuples `(a1, a2, ..., aN)` and `(b1, b2, ..., bN)`, the first
/// tuple is after the second tuple if and only if
/// `a1 > b1` or (`a1 == b1` and
/// `(a2, ..., aN) > (b2, ..., bN)`).
///
/// - Parameters:
/// - lhs: A tuple of `Comparable` elements.
/// - rhs: Another tuple of elements of the same type as `lhs`.
@_alwaysEmitIntoClient
public func > <each B: Comparable>(lhs: (repeat each B), rhs: (repeat each B)) -> Bool {
for (lhs, rhs) in repeat (each lhs, each rhs) {
if lhs <= rhs {
return false
}
}
return true
}

/// Returns a Boolean value indicating whether the first tuple is ordered
/// after or the same as the second in a lexicographical ordering.
///
/// Given two tuples `(a1, a2, ..., aN)` and `(b1, b2, ..., bN)`, the first
/// tuple is after or the same as the second tuple if and only if
/// `a1 > b1` or (`a1 == b1` and
/// `(a2, ..., aN) >= (b2, ..., bN)`).
///
/// - Parameters:
/// - lhs: A tuple of `Comparable` elements.
/// - rhs: Another tuple of elements of the same type as `lhs`.
@_alwaysEmitIntoClient
public func >= <each B: Comparable>(lhs: (repeat each B), rhs: (repeat each B)) -> Bool {
for (lhs, rhs) in repeat (each lhs, each rhs) {
if lhs < rhs {
return false
}
}
return true
}

// MARK: - Old vestigial ABI symbols for old variadic tuple methods.

@usableFromInline
@abi(func ==(lhs: (), rhs: ()) -> Bool)
internal func _abi_tupleEqual(lhs: (), rhs: ()) -> Bool {
return true
}

@usableFromInline
@abi(func !=(lhs: (), rhs: ()) -> Bool)
internal func _abi_tupleNotEqual(lhs: (), rhs: ()) -> Bool {
return false
}

@usableFromInline
@abi(func <(lhs: (), rhs: ()) -> Bool)
internal func _abi_tupleLessThan(lhs: (), rhs: ()) -> Bool {
return false
}

@usableFromInline
@abi(func <=(lhs: (), rhs: ()) -> Bool)
internal func _abi_tupleLessThanOrEqual(lhs: (), rhs: ()) -> Bool {
return true
}

@usableFromInline
@abi(func >(lhs: (), rhs: ()) -> Bool)
internal func _abi_tupleGreaterThan(lhs: (), rhs: ()) -> Bool {
return false
}

@usableFromInline
@abi(func >=(lhs: (), rhs: ()) -> Bool)
internal func _abi_tupleGreaterThanOrEqual(lhs: (), rhs: ()) -> Bool {
return true
}

@usableFromInline
@abi(func == <A: Equatable, B: Equatable>(lhs: (A,B), rhs: (A,B)) -> Bool)
internal func _abi_tupleEqual <A: Equatable, B: Equatable>(lhs: (A,B), rhs: (A,B)) -> Bool {
lhs == rhs
}

@usableFromInline
@abi(func != <A: Equatable, B: Equatable>(lhs: (A,B), rhs: (A,B)) -> Bool)
internal func _abi_tupleNotEqual <A: Equatable, B: Equatable>(lhs: (A,B), rhs: (A,B)) -> Bool {
lhs != rhs
}

@usableFromInline
@abi(func < <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool)
internal func _abi_tupleLessThan <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool {
lhs < rhs
}

@usableFromInline
@abi(func <= <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool)
internal func _abi_tupleLessThanOrEqual <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool {
lhs <= rhs
}

@usableFromInline
@abi(func > <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool)
internal func _abi_tupleGreaterThan <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool {
lhs > rhs
}

@usableFromInline
@abi(func >= <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool)
internal func _abi_tupleGreaterThanOrEqual <A: Comparable, B: Comparable>(lhs: (A,B), rhs: (A,B)) -> Bool {
lhs >= rhs
}

@usableFromInline
@abi(func == <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool)
internal func _abi_tupleEqual <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
lhs == rhs
}

@usableFromInline
@abi(func != <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool)
internal func _abi_tupleNotEqual <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
lhs != rhs
}

@usableFromInline
@abi(func < <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool)
internal func _abi_tupleLessThan <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
lhs < rhs
}

@usableFromInline
@abi(func <= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool)
internal func __abi_3TupleLessThanOrEqual <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
lhs <= rhs
}

@usableFromInline
@abi(func > <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool)
internal func __abi_3TupleGreaterThan <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
lhs > rhs
}

@usableFromInline
@abi(func >= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool)
internal func __abi_3TupleGreaterThanOrEqual <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
lhs >= rhs
}

@usableFromInline
@abi(func == <A: Equatable, B: Equatable, C: Equatable, D: Equatable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool)
internal func __abi_4TupleEqual <A: Equatable, B: Equatable, C: Equatable, D: Equatable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool {
lhs == rhs
}

@usableFromInline
@abi(func != <A: Equatable, B: Equatable, C: Equatable, D: Equatable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool)
internal func _abi_tupleNotEqual <A: Equatable, B: Equatable, C: Equatable, D: Equatable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool {
lhs != rhs
}

@usableFromInline
@abi(func < <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool)
internal func _abi_tupleLessThan <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool {
lhs < rhs
}

@usableFromInline
@abi(func <= <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool)
internal func _abi_tupleLessThanOrEqual <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool {
lhs <= rhs
}

@usableFromInline
@abi(func > <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool)
internal func _abi_tupleGreaterThan <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool {
lhs > rhs
}

@usableFromInline
@abi(func >= <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool)
internal func _abi_tupleGreaterThanOrEqual <A: Comparable, B: Comparable, C: Comparable, D: Comparable>(lhs: (A,B,C,D), rhs: (A,B,C,D)) -> Bool {
lhs >= rhs
}

@usableFromInline
@abi(func == <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool)
internal func _abi_tupleEqual <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool {
lhs == rhs
}

@usableFromInline
@abi(func != <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool)
internal func _abi_tupleNotEqual <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool {
lhs != rhs
}

@usableFromInline
@abi(func < <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool)
internal func _abi_tupleLessThan <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool {
lhs < rhs
}

@usableFromInline
@abi(func <= <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool)
internal func _abi_tupleLessThanOrEqual <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool {
lhs <= rhs
}

@usableFromInline
@abi(func > <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool)
internal func _abi_tupleGreaterThan <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool {
lhs > rhs
}

@usableFromInline
@abi(func >= <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool)
internal func _abi_tupleGreaterThanOrEqual <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable>(lhs: (A,B,C,D,E), rhs: (A,B,C,D,E)) -> Bool {
lhs >= rhs
}

@usableFromInline
@abi(func == <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool)
internal func _abi_tupleEqual <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
lhs == rhs
}

@usableFromInline
@abi(func != <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool)
internal func _abi_tupleNotEqual <A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
lhs != rhs
}

@usableFromInline
@abi(func < <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool)
internal func _abi_tupleLessThan <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
lhs < rhs
}

@usableFromInline
@abi(func <= <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool)
internal func _abi_tupleLessThanOrEqual <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
lhs <= rhs
}

@usableFromInline
@abi(func > <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool)
internal func _abi_tupleGreaterThan <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
lhs > rhs
}

@usableFromInline
@abi(func >= <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool)
internal func _abi_tupleGreaterThanOrEqual <A: Comparable, B: Comparable, C: Comparable, D: Comparable, E: Comparable, F: Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
lhs >= rhs
}
Loading