You just need another sorted
overload.
let now: Date = .now
let myData: [MyData] = [
.init(time: .distantFuture),
.init(time: .distantPast),
.init(time: now)
]
#expect(
myData.sorted(by: \.time).map(\.time) == [
.distantPast, now, .distantFuture
]
)
public extension Sequence {
@inlinable func sorted<each Comparable: Swift.Comparable, Error>(
by comparable: (Element) throws(Error) -> (repeat each Comparable)
) throws(Error) -> [Element] {
do {
return try sorted { try (repeat each comparable($0)) < (repeat each comparable($1)) }
} catch {
throw error as! Error
}
}
}
@inlinable public func < <each Element: Comparable>(
_ element0: (repeat each Element),
_ element1: (repeat each Element)
) -> Bool {
for elements in repeat (each element0, each element1) {
if elements.0 < elements.1 { return true }
if elements.0 > elements.1 { return false }
}
return false
}
(I've tried to figure out how/if you could pass in >
, instead of having to reverse the sorted array, but the compiler gets crashy with parameter packs. It's easy if you don't use packs.)
let sortedDates = myData.sorted(by: \.time).map(\.time)
#expect(sortedDates == [.distantPast, now, .distantFuture])
#expect(myData.sorted(by: \.time, >).map(\.time) == sortedDates.reversed())
public extension Sequence {
@inlinable func sorted<Comparable: Swift.Comparable, Error>(
by comparable: (Element) throws(Error) -> Comparable,
_ areInIncreasingOrder: (Comparable, Comparable) throws(Error) -> Bool = (<)
) throws(Error) -> [Element] {
do {
return try sorted {
try areInIncreasingOrder(comparable($0), comparable($1))
}
} catch {
throw error as! Error
}
}
// This should be covered by the other overload,
// but using that one with `Never` crashes the compiler.
@inlinable func sorted<Comparable: Swift.Comparable>(
by comparable: (Element) -> Comparable,
_ areInIncreasingOrder: (Comparable, Comparable) -> Bool = (<)
) -> [Element] {
sorted {
areInIncreasingOrder(comparable($0), comparable($1))
}
}
}