2017-02-06 4 views
0

This article zeigt: ?? ist sehr zeitaufwendig, und der Test hat es gefunden, um wahr zu sein. Deshalb möchte ich dies optimieren:Mehrdeutige Verwendung von Operator '??'

#if DEBUG 
public func ?? <T>(left: T?, right: T) -> T { 
    guard let value = left else { 
     return right 
    } 
    return value 
} 
#endif 

ABER

string = string ?? "" 

ERROR: Ambiguous use of operator '??'

Antwort

0

Der Artikel, den Sie verknüpfen beschreibt nicht, wie die nil koaleszierende Operator „zeitraubend“ ist, sondern gibt die einfache Tatsache, dass ein zusammengesetzter Ausdruck von zwei zusammenfassenden Operatoraufrufen sowie anderen Auswertungen hat eine wesentlich längere Erstellungszeit als wenn wir diese zusammengesetzten Ausdrücke in kleinere Teile zerlegen, besonders wenn der erstere zu einem gewissen Zeitpunkt faule Auswertungen enthält (was z Auswertung der rhs des Operators ??). Indem wir komplexe Ausdrücke zerlegen, helfen wir dem Kompilierer; Es ist bekannt, dass Swift Schwierigkeiten hat, komplexe zusammengesetzte Anweisungen zu kompilieren, daher wird dies erwartet. Dies sollte jedoch Laufzeitleistung im Allgemeinen nicht beeinträchtigen, da Sie Ihre Implementierung für den Release-Modus erstellen.

die Umsetzung des ?? Bediener während des Debug mit einer nicht faul Auswertung der lhsDurch Überlastung während noch lange zusammengesetzte Anweisungen verwenden, sollte nicht in vollem Umfang das Problem in der vorherige Klausel beschrieben einzulösen. Wenn die Kompilierzeit wirklich ein Problem für Sie ist, verwenden Sie den gleichen Ansatz wie der Autor des Artikels; Zerlegen Sie Ihre komplexen Ausdrücke in mehrere kleinere, und erledigen Sie selbst einige Arbeiten des Compilers. Refactoring mit dem einzigen Zweck, die Kompilierungszeiten zu verringern (was wir vielleicht für die Aufgabe des Compilers halten, nicht für uns), könnte manchmal frustrierend sein, aber es ist ein Problem, mit dem wir (derzeit) leben müssen, wenn wir mit Swift arbeiten. Siehe z.B. der folgende ausgezeichnete Artikel beschreibt die Swift-Compiler Probleme mit langer/komplexer Ausdrücke abdecken:


w.r.t. der Mehrdeutigkeit Fehler:

@_transparent 
public func ?? <T>(optional: T?, defaultValue: @autoclosure() throws -> T) 
    rethrows -> T { 
    switch optional { 
    case .some(let value): 
    return value 
    case .none: 
    return try defaultValue() 
    } 
} 

Und wir können beachten Sie, dass es die gleiche Spezifität wie Ihre eigene generische Implementierung, (vergleiche die Unterschriften!): als Referenz, kann die offizielle Umsetzung des nil coelescing Betreiber here finden was bedeutet, dass der Mehrdeutigkeitsfehler zu erwarten ist. Z.B., Zu vergleichen mit:

// due to the '@autoclosure', these two have the 
// same precedecence/specificity in the overload 
// resolution of 'foo(_:)' 
func foo<T>(_ obj: T) {} 
func foo<T>(_ closure: @autoclosure() -> T) {} 
foo("foo") // ERROR at line 9, col 1: ambiguous use of 'foo' 

Wenn Sie Ihre ?? Überlastung es wie in Ihrer Antwort implementieren, die Eingabe aus Any, wird diese Implementierung spezifischer als die generischen ein, was bedeutet, es Vorrang bei der Überladungsauflösung von ?? zu nehmen. Mit Any ist solche Kontexte jedoch im Allgemeinen eine schlechte Idee, die versucht, dynamische Typisierung nachzuahmen, anstatt sich auf Swifts bekannte statische Typisierung zu verlassen.

+0

Vielen Dank für Ihre ausführliche Erklärung. Ich werde die zeitraubenden Operatoren aufteilen, um die Kompilierzeit zu verbessern. z.B. für _ in [0 .. <100] { str = str ?? "" } –

0

wenn ich ?? Überlastung, ich nicht <T> verwenden können ...

dann

#if DEBUG 
public func ?? (left: Any?, right: Any) -> Any { 
    guard let value = left else { 
     return right 
    } 
    return value 
} 
#endif 

ist OK!

ABER ich nicht Typen Rückgabewert bekommen ...

Verwandte Themen