Nach meiner jüngsten Exposition gegenüber Python, lernte ich die Lesbarkeit seiner conditional expressions mit der Form X if C else Y
schätzen zu schätzen.Python-Stil konditionalen Ausdruck in Swift 3
Wenn die klassische ternary conditional operator ?: die Bedingung als erstes Argument hat, fühlt es sich an, als ob die Aufgabe sich auf die Wahl bezieht. Es wird hässlich, wenn Sie versuchen, mehrere ternäre Operatoren zu verschachteln ... Wenn die Bedingung nach dem ersten Ausdruck verschoben wird, fühlt es sich eher wie eine mathematische Definition einer Funktion an. Ich finde das hilft manchmal bei der Code-Klarheit.
Wie code kata wollte ich in Swift Python-Stil bedingten Ausdruck implementieren. Es scheint, als ob das einzige Werkzeug, das mir die erforderliche Syntax bringen kann, benutzerdefinierte Operatoren sind. Sie müssen aus Symbolen bestehen. Math symbols in Unicode Etikett des double turnstile Symbol von Logik als TRUE ⊨
und Version durchgestrichen ist NICHT WAHR ⊭
... so ging ich mit ==|
und |!=
. Bisher nachdem eine Zeit lang im Kampf gegen den richtigen Vorrang zu finden, ich habe dies:
// Python-like conditional expression
struct CondExpr<T> {
let cond: Bool
let expr:() -> T
}
infix operator ==| : TernaryPrecedence // if/where
infix operator |!= : TernaryPrecedence // else
func ==|<T> (lhs: @autoclosure() -> T, rhs: CondExpr<T>) -> T {
return rhs.cond ? lhs() : rhs.expr()
}
func |!=<T> (lhs: Bool, rhs: @escaping @autoclosure() -> T) -> CondExpr<T> {
return CondExpr<T>(cond: lhs, expr: rhs)
}
Ich weiß, dass das Ergebnis nicht sehr sieht swifty oder besonders lesbar, aber auf der hellen Seite, diese Operatoren Arbeit auch wenn der Ausdruck über mehrere Zeilen verteilt ist.
let e = // is 12 (5 + 7)
1 + 3 ==| false |!=
5 + 7 ==| true |!=
19 + 23
Wenn Sie mit Leerzeichen kreativ, es fühlt sich sogar ein wenig pythonic:
let included =
Set(filters) ==| !filters.isEmpty |!=
Set(precommitTests.keys) ==| onlyPrecommit |!=
Set(allTests.map { $0.key })
Ich mag es nicht, dass die zweite autoclosure Flucht werden muss. Nate Cook's answer about custom ternary operators in Swift 2 verwendete Currysyntax, die nicht mehr in Swift 3 ist ... und ich vermute, das war technisch auch eine flüchtige Schließung.
Gibt es eine Möglichkeit, dies zu bewerkstelligen, ohne die Schließung zu umgehen? Ist es überhaupt wichtig? Vielleicht ist der Swift-Compiler schlau genug, um dies während der Kompilierungszeit zu beheben, so dass es keine Auswirkungen auf die Laufzeit hat?
Schön. Du könntest diesen zweiten Funktionskörper etwas hübscher machen, vielleicht: https://gist.github.com/woolsweater/4da0dc0bb348fb40a2becb1aec9a2890 –
Danke für dieses Feedback. Ich räume meine Antwort auf. –
Der erste Funktionskörper kann geschrieben werden als 'return rhs ?? lhs() ' –