Se ho capito bene, Swift può determinare il tipo effettivo di generici con diversi mezzi, incluso il matching per tipo di ritorno. Lo stesso meccanismo (o un meccanismo simile) è usato per disambiguare le funzioni sovraccariche. Quindi, questo funziona come previsto:La selezione del tipo generico Swift non si propaga
func getValue<T>()->T? {
return nil
}
func getValue()->Int? {
return 13
}
let b: Int? = getValue()
Quando si esegue questa, b sarà 13
. Tecnicamente, entrambe le firme delle funzioni sono adeguate, ma quest'ultima è più specifica del tipo di reso richiesto.
Aggiungiamo una seconda funzione e la chiamata tunnel attraverso di esso:
func getGetValue<T>()->T? {
return getValue()
}
let c: Int? = getGetValue()
Quando si esegue questa operazione, c sarà nil
. Infatti, il compilatore selezionerà l'implementazione generica getValue() da chiamare da getGetValue(), che non è quello che voglio. IMHO, il tipo di reso richiesto deve propagarsi attraverso il secondo generico quando si sceglie tra le due implementazioni di getValue(), con lo stesso comportamento del primo esempio.
Cosa mi manca? (Xcode 7.1)
Eccellente scoperta. La mia ipotesi è che infer-by-return-type non funzioni quando c'è un altro livello di astrazione. Una volta all'interno di 'getGetValue', il compilatore non ha idea che il tipo' T' sia, quindi la prima funzione è l'unica che corrisponde. –
@ZoffDino Questa sarebbe la mia ipotesi, ma non capisco perché il compilatore non possa propagare i tipi dal basso verso l'alto. Dal mio punto di vista, sembra un insetto - ma non sono un tipo da compilatore. Forse c'è un motivo perfettamente valido per questo comportamento. Inserirò un radar, per ogni evenienza. –
C'è una voce nel blog Swift [Sicurezza della memoria: i valori di sicurezza sono definiti prima dell'uso] (https://developer.apple.com/swift/blog/?id=28) che spiega fino a che punto il compilatore va a dimostrare la correttezza del programma. Penso che sia in qualche modo pertinente alla tua domanda –