Vedo che ci sono già una serie di buone risposte. Alcune delle quali ripeterò, ma a volte vuoi solo mettere le cose con parole tue. Commenterò con alcuni esempi di C ++ perché è la lingua con cui ho più familiarità.
Ciò che è necessario non è mai saggio. L'inferenza del tipo è necessaria per rendere pratiche le altre funzionalità linguistiche. In C ++ è possibile avere tipi non avvertibili.
struct {
double x, y;
} p0 = { 0.0, 0.0 };
// there is no name for the type of p0
auto p1 = p0;
C ++ 11 ha aggiunto lambda che sono anche indicibili.
auto sq = [](int x) {
return x * x;
};
// there is no name for the type of sq
L'inferenza di tipo è anche alla base dei modelli.
template <class x_t>
auto sq(x_t const& x)
{
return x * x;
}
// x_t is not known until it is inferred from an expression
sq(2); // x_t is int
sq(2.0); // x_t is double
Ma le tue domande erano "perché dovrei, il programmatore, voler dedurre il tipo delle mie variabili quando leggo il codice? Non è più veloce per chiunque solo leggere il tipo che pensare che tipo c'è? "
L'ingerenza del tipo rimuove la ridondanza. Quando si tratta di leggere il codice a volte può essere più veloce e più facile avere informazioni ridondanti nel codice, ma la ridondanza può oscurare le informazioni utili . Ad esempio:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
Non richiede molta familiarità con la libreria standard per un programmatore C ++ per identificare che i è un iteratore da i = v.begin()
, quindi la dichiarazione del tipo esplicito ha un valore limitato. Con la sua presenza oscura i dettagli che sono più importanti (ad esempio che i
punti all'inizio del vettore). La bella risposta di @amon fornisce un esempio ancora migliore di verbosità che oscura dettagli importanti. Al contrario, l'inferenza di tipo dà maggiore risalto ai dettagli importanti.
std::vector<int> v;
auto i = v.begin();
Mentre leggere il codice è importante, non è sufficiente, a un certo punto dovrai smettere di leggere e iniziare a scrivere un nuovo codice. La ridondanza nel codice rende la modifica del codice più lenta e più difficile. Ad esempio, supponiamo di avere il seguente frammento di codice:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
Nel caso in cui ho bisogno di cambiare il tipo di valore del vettore per raddoppiare cambiando il codice in:
std::vector<double> v;
std::vector<double>::iterator i = v.begin();
In questo caso devo modificare il codice in due punti. Contrasto con inferenza di tipo in cui il codice originale è:
std::vector<int> v;
auto i = v.begin();
E il codice modificato:
std::vector<double> v;
auto i = v.begin();
Nota che ora devo solo cambiare una riga di codice. Estrapolarlo a un programma di grandi dimensioni e digitare l'inferenza può propagare le modifiche ai tipi molto più rapidamente di quanto sia possibile con un editor.
La ridondanza nel codice crea la possibilità di bug. Ogni volta che il tuo codice dipende da due informazioni mantenute equivalenti, c'è una possibilità di errore. Ad esempio, c'è un'incongruenza tra i due tipi in questa affermazione che probabilmente non è intesa:
int pi = 3.14159;
La ridondanza rende più difficile discernere le intenzioni. In alcuni casi l'inferenza di tipo può essere più facile da leggere e capire perché è più semplice delle specifiche di tipo esplicite. Considera il frammento di codice:
int y = sq(x);
Nel caso in cui sq(x)
restituisca un int
, non è ovvio se y
è un int
perché è il tipo di ritorno di sq(x)
o perché si adatta alle istruzioni che usano y
. Se cambio altro codice in modo che sq(x)
non restituisca più int
, è incerto da quella sola riga se il tipo di y
debba essere aggiornato. Contrasto con lo stesso codice ma usando inferenza di tipo:
auto y = sq(x);
In questo l'intento è chiaro, y
deve essere dello stesso tipo restituito da sq(x)
. Quando il codice cambia il tipo di ritorno di sq(x)
, il tipo di y
cambia per corrispondere automaticamente.
In C ++ c'è una seconda ragione per cui l'esempio sopra è più semplice con l'inferenza di tipo, l'inferenza di tipo non può introdurre la conversione di tipo implicita. Se il tipo di ritorno di sq(x)
non è int
, il compilatore inserisce silenziosamente una conversione implicita in int
. Se il tipo di ritorno di sq(x)
è un tipo di tipo complesso che definisce operator int()
, questa chiamata di funzione nascosta può essere arbitrariamente complessa.