Skip to content

Commit 38362bb

Browse files
authored
Merge pull request #3522 from apple/stdlib-move-Equatable-Comparable-Hashable
2 parents 5454b86 + 4cd4105 commit 38362bb

File tree

6 files changed

+523
-480
lines changed

6 files changed

+523
-480
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@ set(SWIFTLIB_ESSENTIAL
3737
CocoaArray.swift
3838
Collection.swift
3939
CollectionAlgorithms.swift.gyb
40+
Comparable.swift
4041
CompilerProtocols.swift
4142
ClosedRange.swift
4243
ContiguousArrayBuffer.swift
4344
CString.swift
4445
CTypes.swift
4546
DebuggerSupport.swift
4647
EmptyCollection.swift
48+
Equatable.swift
4749
ErrorType.swift
4850
Existential.swift
4951
Filter.swift.gyb
@@ -53,6 +55,7 @@ set(SWIFTLIB_ESSENTIAL
5355
FloatingPoint.swift.gyb
5456
FloatingPointParsing.swift.gyb
5557
FloatingPointTypes.swift.gyb
58+
Hashable.swift
5659
HashedCollections.swift.gyb
5760
Hashing.swift
5861
HeapBuffer.swift

stdlib/public/core/Comparable.swift

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// A type that can be compared using the relational operators `<`, `<=`, `>=`,
14+
/// and `>`.
15+
///
16+
/// The `Comparable` protocol is used for types that have an inherent order,
17+
/// such as numbers and strings. Many types in the standard library already
18+
/// conform to the `Comparable` protocol. Add `Comparable` conformance to your
19+
/// own custom types when you want to be able to compare instances using
20+
/// relational operators or use standard library methods that are designed for
21+
/// `Comparable` types.
22+
///
23+
/// The most familiar use of relational operators is to compare numbers, as in
24+
/// the following example:
25+
///
26+
/// let currentTemp = 73
27+
///
28+
/// if currentTemp >= 90 {
29+
/// print("It's a scorcher!")
30+
/// } else if currentTemp < 65 {
31+
/// print("Might need a sweater today.")
32+
/// } else {
33+
/// print("Seems like picnic weather!")
34+
/// }
35+
/// // Prints "Seems like picnic weather!"
36+
///
37+
/// You can use special versions of some sequence and collection operations
38+
/// when working with a `Comparable` type. For example, if your array's
39+
/// elements conform to `Comparable`, you can call the `sort()` method without
40+
/// using arguments to sort the elements of your array in ascending order.
41+
///
42+
/// var measurements = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
43+
/// measurements.sort()
44+
/// print(measurements)
45+
/// // Prints "[1.1, 1.2, 1.2, 1.3, 1.5, 1.5, 2.9]"
46+
///
47+
/// Conforming to the Comparable Protocol
48+
/// =====================================
49+
///
50+
/// Types with Comparable conformance implement the less-than operator (`<`)
51+
/// and the is-equal-to operator (`==`). These two operations impose a strict
52+
/// total order on the values of a type, in which exactly one of the following
53+
/// must be true for any two values `a` and `b`:
54+
///
55+
/// - `a == b`
56+
/// - `a < b`
57+
/// - `b < a`
58+
///
59+
/// In addition, the following conditions must hold:
60+
///
61+
/// - `a < a` is always `false` (Irreflexivity)
62+
/// - `a < b` implies `!(b < a)` (Asymmetry)
63+
/// - `a < b` and `b < c` implies `a < c` (Transitivity)
64+
///
65+
/// To add `Comparable` conformance to your custom types, define the `<` and
66+
/// `==` operators. The `==` operator is a requirement of the `Equatable`
67+
/// protocol, which `Comparable` extends---see that protocol's documentation
68+
/// for more information about equality in Swift. Because default
69+
/// implementations of the remainder of the relational operators are provided
70+
/// by the standard library, you'll be able to use `!=`, `>`, `<=`, and `>=`
71+
/// with instances of your type without any further code.
72+
///
73+
/// As an example, here's an implementation of a `Date` structure that stores
74+
/// the year, month, and day of a date:
75+
///
76+
/// struct Date {
77+
/// let year: Int
78+
/// let month: Int
79+
/// let day: Int
80+
/// }
81+
///
82+
/// To add `Comparable` conformance to `Date`, first declare conformance to
83+
/// `Comparable` and implement the `<` operator function.
84+
///
85+
/// extension Date: Comparable { }
86+
///
87+
/// func <(lhs: Date, rhs: Date) -> Bool {
88+
/// if lhs.year != rhs.year {
89+
/// return lhs.year < rhs.year
90+
/// } else if lhs.month != rhs.month {
91+
/// return lhs.month < rhs.month
92+
/// } else {
93+
/// return lhs.day < rhs.day
94+
/// }
95+
/// }
96+
///
97+
/// This function uses the least specific nonmatching property of the date to
98+
/// determine the result of the comparison. For example, if the two `year`
99+
/// properties are equal but the two `month` properties are not, the date with
100+
/// the lesser value for `month` is the lesser of the two dates.
101+
///
102+
/// Next, implement the `==` operator function, the requirement inherited from
103+
/// the `Equatable` protocol.
104+
///
105+
/// func ==(lhs: Date, rhs: Date) -> Bool {
106+
/// return lhs.year == rhs.year && lhs.month == rhs.month
107+
/// && lhs.day == rhs.day
108+
/// }
109+
///
110+
/// Two `Date` instances are equal if each of their corresponding properties is
111+
/// equal.
112+
///
113+
/// Now that `Date` conforms to `Comparable`, you can compare instances of the
114+
/// type with any of the relational operators. The following example compares
115+
/// the date of the first moon landing with the release of David Bowie's song
116+
/// "Space Oddity":
117+
///
118+
/// let spaceOddity = Date(year: 1969, month: 7, day: 11) // July 11, 1969
119+
/// let moonLanding = Date(year: 1969, month: 7, day: 20) // July 20, 1969
120+
/// if moonLanding > spaceOddity {
121+
/// print("Major Tom stepped through the door first.")
122+
/// } else {
123+
/// print("David Bowie was following in Neil Armstrong's footsteps.")
124+
/// }
125+
/// // Prints "Major Tom stepped through the door first."
126+
///
127+
/// Note that the `>` operator provided by the standard library is used in this
128+
/// example, not the `<` operator implemented above.
129+
///
130+
/// - Note: A conforming type may contain a subset of values which are treated
131+
/// as exceptional---that is, values that are outside the domain of
132+
/// meaningful arguments for the purposes of the `Comparable` protocol. For
133+
/// example, the special not-a-number (`FloatingPoint.nan`) value for
134+
/// floating-point types compares as neither less than, greater than, nor
135+
/// equal to any normal floating-point value. Exceptional values need not
136+
/// take part in the strict total order.
137+
public protocol Comparable : Equatable {
138+
/// Returns a Boolean value indicating whether the value of the first
139+
/// argument is less than that of the second argument.
140+
///
141+
/// This function is the only requirement of the `Comparable` protocol. The
142+
/// remainder of the relational operator functions are implemented by the
143+
/// standard library for any type that conforms to `Comparable`.
144+
///
145+
/// - Parameters:
146+
/// - lhs: A value to compare.
147+
/// - rhs: Another value to compare.
148+
func < (lhs: Self, rhs: Self) -> Bool
149+
150+
/// Returns a Boolean value indicating whether the value of the first
151+
/// argument is less than or equal to that of the second argument.
152+
///
153+
/// - Parameters:
154+
/// - lhs: A value to compare.
155+
/// - rhs: Another value to compare.
156+
func <= (lhs: Self, rhs: Self) -> Bool
157+
158+
/// Returns a Boolean value indicating whether the value of the first
159+
/// argument is greater than or equal to that of the second argument.
160+
///
161+
/// - Parameters:
162+
/// - lhs: A value to compare.
163+
/// - rhs: Another value to compare.
164+
func >= (lhs: Self, rhs: Self) -> Bool
165+
166+
/// Returns a Boolean value indicating whether the value of the first
167+
/// argument is greater than that of the second argument.
168+
///
169+
/// - Parameters:
170+
/// - lhs: A value to compare.
171+
/// - rhs: Another value to compare.
172+
func > (lhs: Self, rhs: Self) -> Bool
173+
}
174+
175+
/// Returns a Boolean value indicating whether the value of the first argument
176+
/// is greater than that of the second argument.
177+
///
178+
/// This is the default implementation of the greater-than operator (`>`) for
179+
/// any type that conforms to `Comparable`.
180+
///
181+
/// - Parameters:
182+
/// - lhs: A value to compare.
183+
/// - rhs: Another value to compare.
184+
public func > <T : Comparable>(lhs: T, rhs: T) -> Bool {
185+
return rhs < lhs
186+
}
187+
188+
/// Returns a Boolean value indicating whether the value of the first argument
189+
/// is less than or equal to that of the second argument.
190+
///
191+
/// This is the default implementation of the less-than-or-equal-to
192+
/// operator (`<=`) for any type that conforms to `Comparable`.
193+
///
194+
/// - Parameters:
195+
/// - lhs: A value to compare.
196+
/// - rhs: Another value to compare.
197+
public func <= <T : Comparable>(lhs: T, rhs: T) -> Bool {
198+
return !(rhs < lhs)
199+
}
200+
201+
/// Returns a Boolean value indicating whether the value of the first argument
202+
/// is greater than or equal to that of the second argument.
203+
///
204+
/// This is the default implementation of the greater-than-or-equal-to operator
205+
/// (`>=`) for any type that conforms to `Comparable`.
206+
///
207+
/// - Parameters:
208+
/// - lhs: A value to compare.
209+
/// - rhs: Another value to compare.
210+
/// - Returns: `true` if `lhs` is greater than or equal to `rhs`; otherwise,
211+
/// `false`.
212+
public func >= <T : Comparable>(lhs: T, rhs: T) -> Bool {
213+
return !(lhs < rhs)
214+
}
215+

0 commit comments

Comments
 (0)