Ich finde das mehr als alles andere amüsant. Ich habe es behoben, aber ich wundere mich über die Ursache. Hier ist der Fehler : DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
. Warum beschwert es sich? Es scheint einer der einfachsten Ausdrücke zu sein, die möglich sind.
Der Compiler zeigt auf den columns + ");";
Abschnitt
func tableName() -> String { return("users"); }
func createTableStatement(schema: [String]) -> String {
var schema = schema;
schema.append("id string");
schema.append("created integer");
schema.append("updated integer");
schema.append("model blob");
var columns: String = ",".join(schema);
var statement = "create table if not exists " + self.tableName() + "(" + columns + ");";
return(statement);
}
Das Update ist:
var statement = "create table if not exists " + self.tableName();
statement += "(" + columns + ");";
das funktioniert auch (via @efischency) aber ich mag es nicht so sehr, weil ich denke das geht (
verloren:
var statement = "create table if not exists \(self.tableName()) (\(columns))"
ios
xcode
swift
compiler-errors
functional-programming
Kendrick Taylor
quelle
quelle
var statement = "create table if not exists \(self.tableName()) (\(columns))"
?+
.Antworten:
Ich bin kein Experte für Compiler - ich weiß nicht, ob diese Antwort "Ihre Denkweise auf sinnvolle Weise ändern wird", aber ich verstehe das Problem folgendermaßen:
Es hat mit Typinferenz zu tun. Jedes Mal, wenn Sie den
+
Operator verwenden, muss Swift alle möglichen Überladungen durchsuchen+
und daraus schließen, welche Version von+
Ihnen verwendet wird. Ich habe knapp 30 Überladungen für den+
Bediener gezählt. Das sind viele Möglichkeiten, und wenn Sie 4 oder 5+
Operationen miteinander verketten und den Compiler bitten, alle Argumente abzuleiten, fragen Sie viel mehr, als es auf den ersten Blick erscheinen mag.Diese Schlussfolgerung kann kompliziert werden. Wenn Sie beispielsweise ein
UInt8
und einInt
using hinzufügen+
, ist die Ausgabe einInt
, aber es gibt einige Arbeiten, die in die Bewertung der Regeln für das Mischen von Typen mit Operatoren einfließen.Und wenn Sie Literale verwenden, wie die
String
Literale in Ihrem Beispiel, erledigt der Compiler die Arbeit, dasString
Literal in a zu konvertierenString
und dann das Argument und die Rückgabetypen für den+
Operator usw. abzuleiten .Wenn ein Ausdruck ausreichend komplex ist, dh der Compiler muss zu viele Rückschlüsse auf die Argumente und Operatoren ziehen, wird er beendet und weist Sie darauf hin, dass er beendet wird.
Es ist beabsichtigt, den Compiler zu beenden, sobald ein Ausdruck eine bestimmte Komplexität erreicht. Die Alternative besteht darin, den Compiler versuchen zu lassen, dies zu tun, und zu prüfen, ob dies möglich ist. Dies ist jedoch riskant. Der Compiler könnte es für immer versuchen, festsitzen oder einfach abstürzen. Mein Verständnis ist also, dass es einen statischen Schwellenwert für die Komplexität eines Ausdrucks gibt, über den der Compiler nicht hinausgeht.
Ich verstehe, dass das Swift-Team an Compiler-Optimierungen arbeitet, die diese Fehler seltener machen. Klicken Sie auf diesen Link, um in den Apple Developer-Foren ein wenig darüber zu erfahren .
In den Dev-Foren hat Chris Lattner die Leute gebeten, diese Fehler als Radarberichte einzureichen, weil sie aktiv daran arbeiten, sie zu beheben.
So verstehe ich es, nachdem ich einige Beiträge hier und im Dev-Forum darüber gelesen habe, aber mein Verständnis von Compilern ist naiv, und ich hoffe, dass jemand mit einem tieferen Wissen darüber, wie er mit diesen Aufgaben umgeht, meine Arbeit erweitert habe hier geschrieben.
quelle
Dies ist fast die gleiche wie die akzeptierte Antwort, aber mit einigen zusätzlichen Dialogen (ich hatte mit Rob Napier, seinen anderen Antworten und Matt, Oliver, David von Slack) und Links.
Siehe die Kommentare in dieser Diskussion. Der Kern davon ist:
+
ist stark überlastet (Apple scheint dies in einigen Fällen behoben zu haben)Der
+
Operator ist stark überlastet, da er derzeit 27 verschiedene Funktionen hat. Wenn Sie also 4 Zeichenfolgen verketten, dh 3+
Operatoren haben, muss der Compiler jedes Mal zwischen 27 Operatoren prüfen , das sind also 27 ^ 3-mal. Aber das ist es nicht.Es wird auch überprüft , ob das
lhs
undrhs
das der+
Funktionen beide gültig sind, wenn sieappend
aufgerufen werden, um das aufgerufene zu kernen . Dort können Sie sehen, dass eine Reihe von etwas intensiven Überprüfungen auftreten können. Wenn die Zeichenfolge nicht zusammenhängend gespeichert ist, scheint dies der Fall zu sein, wenn die Zeichenfolge, mit der Sie sich befassen, tatsächlich mit NSString verbunden ist. Swift muss dann alle Byte-Array-Puffer zu einem einzigen zusammenhängenden Puffer zusammensetzen, was das Erstellen neuer Puffer auf dem Weg erfordert. und dann erhalten Sie schließlich einen Puffer, der die Zeichenfolge enthält, die Sie miteinander verketten möchten.Auf den Punkt gebracht ist es 3 Cluster von Compiler überprüft , die Sie nach unten , dh verlangsamt jeder Unterausdruck hat angesichts der alles überdacht werden es könnte zurückkehren . Als Ergebnis Strings mit Interpolation verketten dh unter Verwendung
" My fullName is \(firstName) \(LastName)"
ist viel besser als"My firstName is" + firstName + LastName
da Interpolation nicht hat jede Überlastung hatSwift 3 hat einige Verbesserungen vorgenommen. Weitere Informationen finden Sie unter Zusammenführen mehrerer Arrays, ohne den Compiler zu verlangsamen. . Trotzdem ist der
+
Operator immer noch überlastet und es ist besser, die String-Interpolation für längere Strings zu verwendenVerwendung von Optionen (laufendes Problem - Lösung verfügbar)
In diesem sehr einfachen Projekt:
Die Kompilierungszeit für die Funktionen ist wie folgt:
Beachten Sie, wie verrückt die Kompilierungsdauer
concatenatedOptionals
ist.Dies kann gelöst werden durch:
welches kompiliert in
88ms
Die Ursache des Problems ist , dass der Compiler identifiziert nicht die
""
als einString
. Es ist eigentlichExpressibleByStringLiteral
Der Compiler sieht alle Typen, die diesem Protokoll entsprechen ,
??
und muss sie durchlaufen , bis er einen Typ findet, der standardmäßig verwendet werden kannString
. Durch die Verwendung vonemptyString
HardcodierungString
muss der Compiler nicht mehr alle konformen Typen von durchlaufenExpressibleByStringLiteral
Informationen zum Protokollieren der Kompilierungszeiten finden Sie hier oder hier
Andere ähnliche Antworten von Rob Napier auf SO:
Warum dauert das Erstellen von Strings so lange?
Wie kann man mehrere Arrays zusammenführen, ohne den Compiler zu verlangsamen?
Swift Array enthält Funktionen, die die Build-Zeiten verlängern
quelle
Das ist ziemlich lächerlich, egal was du sagst! :) :)
Aber das geht leicht vorbei
quelle
Ich hatte ein ähnliches Problem:
In Xcode 9.3 sieht die Zeile folgendermaßen aus:
Nachdem Sie es in so etwas geändert haben:
es hat alles geklappt.
Wahrscheinlich hat es etwas damit zu tun, dass der Swift-Compiler versucht, den Datentyp aus dem Code abzuleiten.
quelle