Swift - Ссылочная функция сравнения по умолчанию как параметр функции - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь реализовать удобную Collection.sorted(by: KeyPath) функцию.

Пока все работает, если сделать

func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
    return sorted { lhs, rhs
        return lhs[keyPath: keyPath] < rhs[keyPath: keyPath]
    }
}

Но что, если я хочу разрешить вызывающей стороне указывать фактические логи сортировки c? Я добавил функцию обратного вызова, чтобы выполнить сравнение, вот так (черпая вдохновение из оригинальной sorted(_:) сигнатуры функции).

func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>, _ compare: (T, T) throws -> Bool) rethrows -> [Element] {
    return try sorted { lhs, rhs in
        return try compare(lhs[keyPath: keyPath], rhs[keyPath: keyPath])
    }
}

Теперь, это все работает, но это означает, что место вызова всегда должно указывать, какой выполнить операцию сортировки.

let sorted = myArray.sorted(by: \.name, <)

Я бы хотел, чтобы по умолчанию она была <, но как я могу ссылаться на оператор < по умолчанию в сигнатуре моей функции?

1 Ответ

0 голосов
/ 24 марта 2020

На самом деле можно ссылаться на непримененную функцию <, заключив ее в скобки (<) при использовании ее в качестве параметра по умолчанию.

func sorted<T: Comparable>(
    by keyPath: KeyPath<Element, T>, 
    _ compare: (T, T) throws -> Bool = (<)
    ) rethrows -> [Element] {
    return try sorted { lhs, rhs in
        return try compare(lhs[keyPath: keyPath], rhs[keyPath: keyPath])
    }
}

Однако в настоящее время существует проблема с компилятор при этом. Даже если < не выдает, компилятор все равно заставит вас использовать try на сайте вызовов.

Отчет об ошибке для этого был открыт довольно давно go, и до сих пор нерешенным. Если вы столкнулись с этим, пожалуйста, проголосуйте: https://bugs.swift.org/browse/SR-1534

Кроме того, как указано в комментариях, функция sorted(by:) на самом деле представляет собой 2 разные функции.

Один требует Comparable и использует < для внутреннего использования, в то время как другой позволяет вам напрямую указать логи сортировки c и, следовательно, не требует соответствия Comparable.

Следовательно, эта удобная сортировка по keyPath все равно потребует 2 функции.

...