Je vois qu'il y a déjà un certain nombre de bonnes réponses. Je vais en répéter certaines, mais parfois, vous voulez simplement mettre les choses dans vos propres mots. Je vais commenter avec quelques exemples de C ++ parce que c'est le langage avec lequel je suis le plus familier.
Ce qui est nécessaire n’est jamais imprudent. L'inférence de type est nécessaire pour rendre pratiques d'autres fonctionnalités du langage. En C ++, il est possible d'avoir des types indicibles.
struct {
double x, y;
} p0 = { 0.0, 0.0 };
// there is no name for the type of p0
auto p1 = p0;
C ++ 11 a ajouté des lambdas qui sont également indéniables.
auto sq = [](int x) {
return x * x;
};
// there is no name for the type of sq
L'inférence de type sous-tend également les modèles.
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
Mais vos questions étaient les suivantes: "Pourquoi le programmeur voudrait-il déduire le type de mes variables lorsque je lis le code? N’est-il pas plus rapide pour quiconque de lire le type que de penser au type qui existe?"
L'inférence de type supprime la redondance. Lorsqu’il s’agit de lire du code, il peut parfois être plus rapide et plus facile d’avoir des informations redondantes dans le code, mais la redondance peut occulter les informations utiles . Par exemple:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
Il ne faut pas beaucoup de connaissances de la bibliothèque standard pour qu'un programmeur C ++ identifie que i est un itérateur de i = v.begin()
sorte que la déclaration de type explicite a une valeur limitée. Par sa présence, il masque les détails les plus importants (tels que i
le début du vecteur). La réponse précise de @amon fournit un exemple encore meilleur de la verbosité qui éclipse les détails importants. En revanche, l'utilisation de l'inférence de type met davantage en évidence les détails importants.
std::vector<int> v;
auto i = v.begin();
Bien que la lecture du code soit importante, cela ne suffit pas. À un moment donné, vous devrez arrêter de lire et commencer à écrire un nouveau code. La redondance dans le code rend la modification du code plus lente et plus difficile. Par exemple, disons que j'ai le fragment de code suivant:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
Dans le cas où j'ai besoin de changer le type de valeur du vecteur pour changer le code deux fois:
std::vector<double> v;
std::vector<double>::iterator i = v.begin();
Dans ce cas, je dois modifier le code à deux endroits. Contraste avec l'inférence de type où le code d'origine est:
std::vector<int> v;
auto i = v.begin();
Et le code modifié:
std::vector<double> v;
auto i = v.begin();
Notez que je n'ai maintenant plus qu'à changer une ligne de code. Extrapolez ceci à un programme volumineux et l'inférence de type peut propager les modifications de types beaucoup plus rapidement qu'avec un éditeur.
La redondance dans le code crée la possibilité de bogues. Chaque fois que votre code dépend de la conservation de deux informations équivalentes, une erreur est possible. Par exemple, il existe une incohérence entre les deux types dans cette instruction qui n’est probablement pas destinée:
int pi = 3.14159;
La redondance rend l’intention plus difficile à discerner. Dans certains cas, l'inférence de type peut être plus facile à lire et à comprendre, car elle est plus simple que la spécification de type explicite. Considérons le fragment de code:
int y = sq(x);
Dans le cas qui sq(x)
renvoie un int
, il n'est pas évident de savoir s'il y
s'agit d'un int
type de retour sq(x)
ou s'il convient aux déclarations utilisées y
. Si je modifie un autre code tel que sq(x)
ne retourne plus int
, il est incertain à partir de cette ligne seule si le type de y
doit être mis à jour. Contrastez avec le même code mais en utilisant l'inférence de type:
auto y = sq(x);
En cela, l'intention est claire, y
doit être du même type que celui renvoyé par sq(x)
. Lorsque le code change le type de retour de sq(x)
, le type dey
changement à faire correspondre automatiquement.
En C ++, il y a une deuxième raison pour laquelle l'exemple ci-dessus est plus simple avec l'inférence de type. L'inférence de type ne peut pas introduire de conversion de type implicite. Si le type de retour sq(x)
n'est pas int
, le compilateur insère silencieusement une conversion implicite en int
. Si le type de retour sq(x)
est un type complexe qui définit operator int()
, cet appel de fonction masqué peut être arbitrairement complexe.