blob: f519cadea2fcb71706c74900c48b0f4cdd3b4387 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
/// A type that can be compared using the relational operators `<`, `<=`, `>=`,
/// and `>`.
///
/// The `Comparable` protocol is used for types that have an inherent order,
/// such as numbers and strings. Many types in the standard library already
/// conform to the `Comparable` protocol. Add `Comparable` conformance to your
/// own custom types when you want to be able to compare instances using
/// relational operators or use standard library methods that are designed for
/// `Comparable` types.
///
/// The most familiar use of relational operators is to compare numbers, as in
/// the following example:
///
/// let currentTemp = 73
///
/// if currentTemp >= 90 {
/// print("It's a scorcher!")
/// } else if currentTemp < 65 {
/// print("Might need a sweater today.")
/// } else {
/// print("Seems like picnic weather!")
/// }
/// // Prints "Seems like picnic weather!"
///
/// You can use special versions of some sequence and collection operations
/// when working with a `Comparable` type. For example, if your array's
/// elements conform to `Comparable`, you can call the `sort()` method without
/// using arguments to sort the elements of your array in ascending order.
///
/// var measurements = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
/// measurements.sort()
/// print(measurements)
/// // Prints "[1.1, 1.2, 1.2, 1.3, 1.5, 1.5, 2.9]"
///
/// Conforming to the Comparable Protocol
/// =====================================
///
/// Types with Comparable conformance implement the less-than operator (`<`)
/// and the equal-to operator (`==`). These two operations impose a strict
/// total order on the values of a type, in which exactly one of the following
/// must be true for any two values `a` and `b`:
///
/// - `a == b`
/// - `a < b`
/// - `b < a`
///
/// In addition, the following conditions must hold:
///
/// - `a < a` is always `false` (Irreflexivity)
/// - `a < b` implies `!(b < a)` (Asymmetry)
/// - `a < b` and `b < c` implies `a < c` (Transitivity)
///
/// To add `Comparable` conformance to your custom types, define the `<` and
/// `==` operators as static methods of your types. The `==` operator is a
/// requirement of the `Equatable` protocol, which `Comparable` extends---see
/// that protocol's documentation for more information about equality in
/// Swift. Because default implementations of the remainder of the relational
/// operators are provided by the standard library, you'll be able to use
/// `!=`, `>`, `<=`, and `>=` with instances of your type without any further
/// code.
///
/// As an example, here's an implementation of a `Date` structure that stores
/// the year, month, and day of a date:
///
/// struct Date {
/// let year: Int
/// let month: Int
/// let day: Int
/// }
///
/// To add `Comparable` conformance to `Date`, first declare conformance to
/// `Comparable` and implement the `<` operator function.
///
/// extension Date: Comparable {
/// static func < (lhs: Date, rhs: Date) -> Bool {
/// if lhs.year != rhs.year {
/// return lhs.year < rhs.year
/// } else if lhs.month != rhs.month {
/// return lhs.month < rhs.month
/// } else {
/// return lhs.day < rhs.day
/// }
/// }
///
/// This function uses the least specific nonmatching property of the date to
/// determine the result of the comparison. For example, if the two `year`
/// properties are equal but the two `month` properties are not, the date with
/// the lesser value for `month` is the lesser of the two dates.
///
/// Next, implement the `==` operator function, the requirement inherited from
/// the `Equatable` protocol.
///
/// static func == (lhs: Date, rhs: Date) -> Bool {
/// return lhs.year == rhs.year && lhs.month == rhs.month
/// && lhs.day == rhs.day
/// }
/// }
///
/// Two `Date` instances are equal if each of their corresponding properties is
/// equal.
///
/// Now that `Date` conforms to `Comparable`, you can compare instances of the
/// type with any of the relational operators. The following example compares
/// the date of the first moon landing with the release of David Bowie's song
/// "Space Oddity":
///
/// let spaceOddity = Date(year: 1969, month: 7, day: 11) // July 11, 1969
/// let moonLanding = Date(year: 1969, month: 7, day: 20) // July 20, 1969
/// if moonLanding > spaceOddity {
/// print("Major Tom stepped through the door first.")
/// } else {
/// print("David Bowie was following in Neil Armstrong's footsteps.")
/// }
/// // Prints "Major Tom stepped through the door first."
///
/// Note that the `>` operator provided by the standard library is used in this
/// example, not the `<` operator implemented above.
///
/// - Note: A conforming type may contain a subset of values which are treated
/// as exceptional---that is, values that are outside the domain of
/// meaningful arguments for the purposes of the `Comparable` protocol. For
/// example, the special "not a number" value for floating-point types
/// (`FloatingPoint.nan`) compares as neither less than, greater than, nor
/// equal to any normal floating-point value. Exceptional values need not
/// take part in the strict total order.
public protocol Comparable: Equatable {
/// Returns a Boolean value indicating whether the value of the first
/// argument is less than that of the second argument.
///
/// This function is the only requirement of the `Comparable` protocol. The
/// remainder of the relational operator functions are implemented by the
/// standard library for any type that conforms to `Comparable`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
static func < (lhs: Self, rhs: Self) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is less than or equal to that of the second argument.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
static func <= (lhs: Self, rhs: Self) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is greater than or equal to that of the second argument.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
static func >= (lhs: Self, rhs: Self) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is greater than that of the second argument.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
static func > (lhs: Self, rhs: Self) -> Bool
}
extension Comparable {
/// Returns a Boolean value indicating whether the value of the first argument
/// is greater than that of the second argument.
///
/// This is the default implementation of the greater-than operator (`>`) for
/// any type that conforms to `Comparable`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
@inlinable
public static func > (lhs: Self, rhs: Self) -> Bool {
return rhs < lhs
}
/// Returns a Boolean value indicating whether the value of the first argument
/// is less than or equal to that of the second argument.
///
/// This is the default implementation of the less-than-or-equal-to
/// operator (`<=`) for any type that conforms to `Comparable`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
@inlinable
public static func <= (lhs: Self, rhs: Self) -> Bool {
return !(rhs < lhs)
}
/// Returns a Boolean value indicating whether the value of the first argument
/// is greater than or equal to that of the second argument.
///
/// This is the default implementation of the greater-than-or-equal-to operator
/// (`>=`) for any type that conforms to `Comparable`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
/// - Returns: `true` if `lhs` is greater than or equal to `rhs`; otherwise,
/// `false`.
@inlinable
public static func >= (lhs: Self, rhs: Self) -> Bool {
return !(lhs < rhs)
}
}