StaticString
è conoscibile al momento della compilazione. Questo può portare a ottimizzazioni. Esempio:
EDIT: Questa parte non funziona, vedere modifica sotto
Supponiamo di avere una funzione che calcola un Int
per alcuni String
valori per alcune costanti che si definiscono al momento della compilazione.
let someString = "Test"
let otherString = "Hello there"
func numberForString(string: String) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
let some = numberForString(someString)
let other = numberForString(otherString)
In questo modo, la funzione vengono eseguite con le "Test" e "Ciao a tutti" quando in realtà viene richiamato nel programma, quando l'applicazione si avvia per esempio. Sicuramente in fase di esecuzione.Tuttavia, se si modifica la funzione di prendere una StaticString
func numberForString(string: StaticString) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
il compilatore sa che il passato in StaticString
è conoscibile al momento della compilazione, quindi indovinate cosa fa? Esegue la funzione proprio al momento della compilazione (Quanto è fantastico!). Una volta ho letto un articolo a riguardo, l'autore ha ispezionato l'assemblaggio generato e ha effettivamente trovato i numeri già calcolati.
Come si può vedere questo può essere utile in alcuni casi come quello menzionato, per non ridurre le prestazioni di runtime per cose che possono essere fatte in fase di compilazione.
MODIFICA: Dániel Nagy e me had a conversation. L'esempio precedente non funziona perché la funzione stringValue
di StaticString
non può essere conosciuta in fase di compilazione (perché restituisce un valore String
). Ecco un esempio migliore:
func countStatic(string: StaticString) -> Int {
return string.byteSize // Breakpoint here
}
func count(string: String) -> Int {
return string.characters.count // Breakpoint here
}
let staticString : StaticString = "static string"
let string : String = "string"
print(countStatic(staticString))
print(count(string))
In una build di rilascio solo il secondo punto di interruzione viene innescato mentre se si cambia la prima funzione a
func countStatic(string: StaticString) -> Int {
return string.stringValue.characters.count // Breakpoint here
}
entrambi i punti di interruzione vengono attivati.
Apparentemente ci sono alcuni metodi che possono essere fatti in fase di compilazione mentre altri non possono. Mi chiedo come il compilatore calcoli questo in realtà.
Sono un po 'confuso riguardo "il valore detenuto dalla variabile sarà determinato al momento della compilazione, solo che qualsiasi valore assegnato ad esso è conoscibile al momento della compilazione." Qual è allora la differenza tra conoscibile al momento della compilazione e determinata in fase di compilazione? E 'StaticString's non può essere mutato, tuttavia possono essere riassegnati pure. Quindi in pratica il compilatore non può essere sicuro del suo valore. –
Il compilatore non sa quale valore una variabile di tipo 'StaticString' manterrà in fase di compilazione, ma sa che qualsiasi valore che verrà assegnato a quella variabile è un letterale di stringa che era noto al momento della compilazione. Quello che Swift farà con queste informazioni è noto solo agli autori di Swift fino a quando non rilasceranno il codice open source. – vacawama
grazie per il chiarimento! –