This extension works in Swift 6.0 and earlier, but I get an error when I use Swift 6.1 in Xcode 16.3 beta 2: "Ambiguous use of operator '>'"
extension Sequence {
func sorted<T: Comparable>(
by keyPath: KeyPath<Element, T>,
ascending: Bool = true
) -> [Element] {
let compareOp: (T, T) -> Bool = ascending ? (<) : (>)
return sorted { a, b in
compareOp(a[keyPath: keyPath], b[keyPath: keyPath])
}
}
}
Not too hard to get around the error, but I'm wondering if there was a change to the language that I missed that makes this invalid now?
2 Likes
Danny
2
-
I don't know what the problem is.
-
Your quick fix is to not use a ternary operator.
let compareOp: (T, _) -> _ = if ascending { (<) } else { (>) }
- Your function is not very versatile. You should not require key paths.
let unsorted = [3, 0, 1, 2, -1]
let sorted = Array(-1...3)
#expect(unsorted.sorted(by: \.self) == sorted)
#expect(unsorted.sorted(by: \.self, >) == sorted.reversed())
let unsortedTuples = [(1, 1), (0, 1), (1, 0), (0, 0)]
let sortedTuples = [(0, 1), (0, 0), (1, 1), (1, 0)]
#expect(unsortedTuples.sorted(by: \.self, (<, >)).elementsEqual(sortedTuples, by: ==))
public extension Sequence {
@inlinable func sorted<Comparable: Swift.Comparable, Error>(
by comparable: (Element) throws(Error) -> Comparable
) throws(Error) -> [Element] {
try sorted(by: comparable, <)
}
@inlinable func sorted<each Comparable: Swift.Comparable, Error>(
by comparable: (Element) throws(Error) -> (repeat each Comparable),
_ areInIncreasingOrder: (repeat (each Comparable, each Comparable) throws(Error) -> Bool)
) throws(Error) -> [Element] {
do {
return try sorted {
for (comparables, areInIncreasingOrder) in
repeat try ((each comparable($0), each comparable($1)), each areInIncreasingOrder) {
if try areInIncreasingOrder(comparables.0, comparables.1) { return true }
if try areInIncreasingOrder(comparables.1, comparables.0) { return false }
}
return false // Equality.
}
} catch { throw error as! Error }
}
}