Skip to content

Instantly share code, notes, and snippets.

@beccadax
Forked from erica/optionalequality.swift
Last active August 31, 2016 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beccadax/60460ad4578d5d8d52a9d736240cfea6 to your computer and use it in GitHub Desktop.
Save beccadax/60460ad4578d5d8d52a9d736240cfea6 to your computer and use it in GitHub Desktop.
// Evaluates the given closure when two `Optional` instances are not `nil`,
// passing the unwrapped values as parameters. (Thanks, Mike Ash, Tim Vermeulen)
// Following the example of IEEE754 with NAN, any comparison involving
// .None is false
//
// See also: http://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values
/// Returns nil if either parameter is nil, or a tuple of the parameters
/// otherwise.
func all<T, U>(_ first: T?, _ second: U?) -> (T, U)? {
return first.flatMap { first in second.flatMap { second in (first, second) } }
}
/// Returns a version of the passed two-parameter function which takes a
/// tuple of parameters instead.
func splatted<T, U, V>(_ function: @escaping (T, U) -> V) -> ((T, U)) -> V {
return { tuple in function(tuple.0, tuple.1) }
}
// MARK: Failable Optional Comparisons
precedencegroup OptionalComparisonPrecedence {
higherThan: NilCoalescingPrecedence
}
infix operator <?: OptionalComparisonPrecedence
infix operator <=?: OptionalComparisonPrecedence
infix operator ==?: OptionalComparisonPrecedence
infix operator >?: OptionalComparisonPrecedence
infix operator >=?: OptionalComparisonPrecedence
/// Returns lhs! < rhs!, otherwise nil
public func<? <T: Comparable>(lhs: T?, rhs: T?) -> Bool? { return all(lhs, rhs).map(splatted(<)) }
/// Returns lhs! <= rhs!, otherwise nil
public func<=? <T: Comparable>(lhs: T?, rhs: T?) -> Bool? { return all(lhs, rhs).map(splatted(<=)) }
/// Returns lhs! == rhs!, otherwise nil
public func==? <T: Comparable>(lhs: T?, rhs: T?) -> Bool? { return all(lhs, rhs).map(splatted(==)) }
/// Returns lhs! > rhs!, otherwise nil
public func>? <T: Comparable>(lhs: T?, rhs: T?) -> Bool? { return all(lhs, rhs).map(splatted(>)) }
/// Returns lhs! >= rhs!, otherwise nil
public func>=? <T: Comparable>(lhs: T?, rhs: T?) -> Bool? { return all(lhs, rhs).map(splatted(>=)) }
// MARK: Unwrapped Optional Comparisons
/// Returns lhs! < rhs!, otherwise false
public func< <T: Comparable>(lhs: T?, rhs: T?) -> Bool { return lhs <? rhs ?? false }
/// Returns lhs! <= rhs!, otherwise false
public func<= <T: Comparable>(lhs: T?, rhs: T?) -> Bool { return lhs <=? rhs ?? false }
/// Returns lhs! == rhs!, otherwise false
public func== <T: Comparable>(lhs: T?, rhs: T?) -> Bool { return lhs ==? rhs ?? false }
/// Returns lhs! > rhs!, otherwise false
public func> <T: Comparable>(lhs: T?, rhs: T?) -> Bool { return lhs >? rhs ?? false }
/// Returns lhs! >= rhs!, otherwise false
public func>= <T: Comparable>(lhs: T?, rhs: T?) -> Bool { return lhs >=? rhs ?? false }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment