Skip to content

Instantly share code, notes, and snippets.

@sidmani
Created October 4, 2017 23:57
Show Gist options
  • Save sidmani/a300d4039a0931715653b994dbd9c349 to your computer and use it in GitHub Desktop.
Save sidmani/a300d4039a0931715653b994dbd9c349 to your computer and use it in GitHub Desktop.
Chaining comparison operators in Swift
infix operator <: AdditionPrecedence
infix operator >: AdditionPrecedence
infix operator <=: AdditionPrecedence
infix operator >=: AdditionPrecedence
class AccumulatedComparison<T: Comparable> {
var result: Bool
var value: T
init(result: Bool, value: T) {
self.result = result
self.value = value
}
@discardableResult func accumulate(_ comparator: (T, T) -> Bool,
nextValue: T) -> Bool {
result = result && comparator(value, nextValue)
value = nextValue
return result
}
}
extension Comparable {
static func <(accumulator: AccumulatedComparison<Self>, right: Self) -> AccumulatedComparison<Self> {
accumulator.accumulate(<, nextValue: right)
return accumulator
}
static func <(accumulator: AccumulatedComparison<Self>, right: Self) -> Bool {
return accumulator.accumulate(<, nextValue: right)
}
static func <(left: Self, right: Self) -> AccumulatedComparison<Self> {
return AccumulatedComparison(result: left < right, value: right)
}
static func >(accumulator: AccumulatedComparison<Self>, right: Self) -> AccumulatedComparison<Self> {
accumulator.accumulate(>, nextValue: right)
return accumulator
}
static func >(accumulator: AccumulatedComparison<Self>, right: Self) -> Bool {
return accumulator.accumulate(>, nextValue: right)
}
static func >(left: Self, right: Self) -> AccumulatedComparison<Self> {
return AccumulatedComparison(result: left > right, value: right)
}
static func >=(accumulator: AccumulatedComparison<Self>, right: Self) -> AccumulatedComparison<Self> {
accumulator.accumulate(>=, nextValue: right)
return accumulator
}
static func >=(accumulator: AccumulatedComparison<Self>, right: Self) -> Bool {
return accumulator.accumulate(>=, nextValue: right)
}
static func >=(left: Self, right: Self) -> AccumulatedComparison<Self> {
return AccumulatedComparison(result: left >= right, value: right)
}
static func <=(accumulator: AccumulatedComparison<Self>, right: Self) -> AccumulatedComparison<Self> {
accumulator.accumulate(<=, nextValue: right)
return accumulator
}
static func <=(accumulator: AccumulatedComparison<Self>, right: Self) -> Bool {
return accumulator.accumulate(<=, nextValue: right)
}
static func <=(left: Self, right: Self) -> AccumulatedComparison<Self> {
return AccumulatedComparison(result: left <= right, value: right)
}
}
// must cast to bool when called independently, not necessary when compiler can infer type (such as in if statements)
(5 < 6 < 7 < 9 >= 9) as Bool // true
(6 >= 0 >= 1) as Bool // false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment