C'est presque la même chose que la réponse acceptée mais avec quelques dialogues supplémentaires (j'ai eu avec Rob Napier, ses autres réponses et Matt, Oliver, David de Slack) et des liens.
Voir les commentaires dans cette discussion. L'essentiel est:
+
est fortement surchargé (Apple semble avoir corrigé ce problème dans certains cas)
L' +
opérateur est fortement surchargé, à partir de maintenant il a 27 fonctions différentes, donc si vous concaténez 4 chaînes, c'est-à-dire que vous avez 3 +
opérateurs, le compilateur doit vérifier entre 27 opérateurs à chaque fois, soit 27 ^ 3 fois. Mais ce n'est pas ça.
Il y a aussi une vérification pour voir si les fonctions lhs
et rhs
des +
fonctions sont toutes les deux valides si elles sont append
appelées à cœur de l' appelé. Là, vous pouvez voir qu'il y a un certain nombre de vérifications quelque peu intensives qui peuvent avoir lieu. Si la chaîne est stockée de manière non contiguë, ce qui semble être le cas si la chaîne que vous traitez est en fait pontée vers NSString. Swift doit ensuite réassembler tous les tampons du tableau d'octets dans un seul tampon contigu et ce qui nécessite la création de nouveaux tampons en cours de route. et vous obtenez finalement un tampon contenant la chaîne que vous essayez de concaténer.
En un mot, il y a 3 groupes de vérifications du compilateur qui vous ralentiront, c'est -à- dire que chaque sous-expression doit être reconsidérée à la lumière de tout ce qu'elle pourrait renvoyer . En conséquence, concaténer des chaînes avec interpolation, c'est-à-dire utiliser " My fullName is \(firstName) \(LastName)"
est bien meilleur que "My firstName is" + firstName + LastName
puisque l'interpolation n'a pas de surcharge
Swift 3 a apporté quelques améliorations. Pour plus d'informations, lisez Comment fusionner plusieurs tableaux sans ralentir le compilateur? . Néanmoins, l' +
opérateur est toujours surchargé et il est préférable d'utiliser l'interpolation de chaîne pour les chaînes plus longues
Utilisation d'options (problème en cours - solution disponible)
Dans ce projet très simple:
import UIKit
class ViewController: UIViewController {
let p = Person()
let p2 = Person2()
func concatenatedOptionals() -> String {
return (p2.firstName ?? "") + "" + (p2.lastName ?? "") + (p2.status ?? "")
}
func interpolationOptionals() -> String {
return "\(p2.firstName ?? "") \(p2.lastName ?? "")\(p2.status ?? "")"
}
func concatenatedNonOptionals() -> String {
return (p.firstName) + "" + (p.lastName) + (p.status)
}
func interpolatedNonOptionals() -> String {
return "\(p.firstName) \(p.lastName)\(p.status)"
}
}
struct Person {
var firstName = "Swift"
var lastName = "Honey"
var status = "Married"
}
struct Person2 {
var firstName: String? = "Swift"
var lastName: String? = "Honey"
var status: String? = "Married"
}
Le temps de compilation des fonctions est comme tel:
21664.28ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:16:10 instance method concatenatedOptionals()
2.31ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:20:10 instance method interpolationOptionals()
0.96ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:24:10 instance method concatenatedNonOptionals()
0.82ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:28:10 instance method interpolatedNonOptionals()
Remarquez à quel point la durée de compilation concatenatedOptionals
est folle .
Cela peut être résolu en faisant:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
qui compile en 88ms
La cause première du problème est que le compilateur n'identifie pas le ""
comme un String
. C'est en faitExpressibleByStringLiteral
Le compilateur verra ??
et devra parcourir tous les types qui se sont conformés à ce protocole , jusqu'à ce qu'il trouve un type qui peut être un type par défaut String
. En utilisant emptyString
qui est codé en dur String
, le compilateur n'a plus besoin de parcourir tous les types conformes deExpressibleByStringLiteral
Pour savoir comment enregistrer les temps de compilation, voir ici ou ici
Autres réponses similaires de Rob Napier sur SO:
Pourquoi l'ajout de chaînes prend si longtemps à construire?
Comment fusionner plusieurs tableaux sans ralentir le compilateur?
Swift Array contient une fonction qui prolonge les temps de construction
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?