Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@porglezomp
Created June 7, 2019 20:45
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 porglezomp/2e9eb8be603f0ae78071a9d5e19daf20 to your computer and use it in GitHub Desktop.
Save porglezomp/2e9eb8be603f0ae78071a9d5e19daf20 to your computer and use it in GitHub Desktop.
Let's do horrible crimes with overloads, in order to get Python-style comparison chaining!
infix operator <: ChainComparison
infix operator >: ChainComparison
infix operator ==: ChainComparison
infix operator !=: ChainComparison
infix operator <=: ChainComparison
infix operator >=: ChainComparison
precedencegroup ChainComparison {
associativity: left
}
struct Comparison<T: Comparable> {
let items: [T]
let comparisons: [Compare]
enum Compare {
case lt, gt, eq, ne, le, ge
func compare(lhs: T, rhs: T) -> Bool {
switch self {
case .lt: return lhs < rhs
case .gt: return lhs > rhs
case .eq: return lhs == rhs
case .ne: return lhs != rhs
case .le: return lhs <= rhs
case .ge: return lhs >= rhs
}
}
}
func eval() -> Bool {
for (i, op) in comparisons.enumerated() {
let (l, r) = (items[i], items[i+1])
if !op.compare(lhs: l, rhs: r) { return false }
}
return true
}
}
func < <T>(lhs: T, rhs: T) -> Comparison<T> {
return Comparison(items: [lhs, rhs], comparisons: [.lt])
}
func < <T>(lhs: Comparison<T>, rhs: T) -> Comparison<T> {
return Comparison(items: lhs.items + [rhs], comparisons: lhs.comparisons + [.lt])
}
func < <T>(lhs: Comparison<T>, rhs: T) -> Bool {
return Comparison(items: lhs.items + [rhs], comparisons: lhs.comparisons + [.lt]).eval()
}
func == <T>(lhs: T, rhs: T) -> Comparison<T> {
return Comparison(items: [lhs, rhs], comparisons: [.eq])
}
func == <T>(lhs: Comparison<T>, rhs: T) -> Comparison<T> {
return Comparison(items: lhs.items + [rhs], comparisons: lhs.comparisons + [.eq])
}
func == <T>(lhs: Comparison<T>, rhs: T) -> Bool {
return Comparison(items: lhs.items + [rhs], comparisons: lhs.comparisons + [.eq]).eval()
}
let x = 2
let y = 3
assert(1 < x < y < 4)
assert(!(1 < y < x < 4))
let z = x
assert(x == z < y == 3)
assert(!(1 < x == z == 3))
let res: Comparison<Int> = 1 < x == z == 3
print(res)
print(res.eval())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment