Widzę, że jest już wiele dobrych odpowiedzi. Niektóre z nich powtórzę, ale czasami po prostu chcesz wyrazić swoje własne słowa. Skomentuję kilka przykładów z C ++, ponieważ jest to język, który znam najbardziej.
To, co jest konieczne, nigdy nie jest nierozsądne. Wnioskowanie typu jest konieczne, aby inne funkcje językowe były praktyczne. W C ++ można mieć typy niewymienne.
struct {
double x, y;
} p0 = { 0.0, 0.0 };
// there is no name for the type of p0
auto p1 = p0;
C ++ 11 dodał lambdy, które również są niewymienne.
auto sq = [](int x) {
return x * x;
};
// there is no name for the type of sq
Wnioskowanie typu stanowi również podstawę szablonów.
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
Ale twoje pytania brzmiały: „dlaczego ja, programista, chciałbym wnioskować o rodzaju moich zmiennych, gdy czytam kod? Czy nie jest szybsze, aby ktokolwiek po prostu czytał ten typ, niż zastanawiał się, jaki on jest?”.
Wnioskowanie typu usuwa nadmiarowość. Jeśli chodzi o odczyt kodu, czasem może być szybsze i łatwiejsze mieć nadmiarowe informacje w kodzie, ale nadmiarowość może przyćmić przydatne informacje . Na przykład:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
Nie trzeba zbytnio zaznajomić się ze standardową biblioteką dla programisty C ++, aby stwierdzić, że i jest iteratorem, i = v.begin()więc deklaracja typu jawnego ma ograniczoną wartość. Swoją obecnością zasłania szczegóły, które są ważniejsze (takie jak iwskazuje na początek wektora). Dobra odpowiedź @amon stanowi jeszcze lepszy przykład gadatliwości przesłaniającej ważne szczegóły. W przeciwieństwie do tego, wnioskowanie na podstawie typu daje większe znaczenie ważnym szczegółom.
std::vector<int> v;
auto i = v.begin();
Podczas gdy czytanie kodu jest ważne, nie jest wystarczające, w pewnym momencie będziesz musiał przestać czytać i zacząć pisać nowy kod. Nadmiarowość kodu powoduje, że modyfikowanie kodu jest wolniejsze i trudniejsze. Powiedzmy, że mam następujący fragment kodu:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
W przypadku, gdy muszę zmienić typ wartości wektora, aby dwukrotnie zmienić kod na:
std::vector<double> v;
std::vector<double>::iterator i = v.begin();
W takim przypadku muszę zmodyfikować kod w dwóch miejscach. Porównaj z wnioskowaniem typu, gdy oryginalny kod to:
std::vector<int> v;
auto i = v.begin();
I zmodyfikowany kod:
std::vector<double> v;
auto i = v.begin();
Zauważ, że teraz muszę zmienić tylko jeden wiersz kodu. Ekstrapoluj to na duży program, a wnioskowanie o typach może propagować zmiany do typów znacznie szybciej niż w edytorze.
Nadmiarowość w kodzie stwarza możliwość błędów. Za każdym razem, gdy kod zależy od zachowania równoważności dwóch informacji, istnieje możliwość pomyłki. Na przykład występuje niespójność między tymi dwoma typami w tej instrukcji, co prawdopodobnie nie jest zamierzone:
int pi = 3.14159;
Redundancja utrudnia rozpoznanie intencji. W niektórych przypadkach wnioskowanie typu może być łatwiejsze do odczytania i zrozumienia, ponieważ jest prostsze niż jawna specyfikacja typu. Rozważ fragment kodu:
int y = sq(x);
W przypadku, gdy sq(x)zwraca an int, nie jest oczywiste, czy yjest to, intponieważ jest to typ zwracany, sq(x)czy dlatego, że pasuje do używanych instrukcji y. Jeśli zmienię inny kod tak, aby sq(x)nie powrócił int, z samej linii nie jest pewne, czy typ ypowinien zostać zaktualizowany. Porównaj z tym samym kodem, ale używając wnioskowania typu:
auto y = sq(x);
W tym celu intencja jest jasna, ymusi być tego samego typu, co zwrócony przez sq(x). Gdy kod zmienia typ zwracany sq(x), typ yzmian jest dopasowywany automatycznie.
W C ++ istnieje drugi powód, dla którego powyższy przykład jest prostszy w przypadku wnioskowania typu, wnioskowanie typu nie może wprowadzać niejawnej konwersji typu. Jeśli zwracany typ sq(x)nie jest int, kompilator po cichu wstawia niejawną konwersję na int. Jeśli typ zwracany sq(x)jest typem złożonym, który definiuje operator int(), to ukryte wywołanie funkcji może być dowolnie złożone.