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 i
wskazuje 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 y
jest to, int
ponieważ 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 y
powinien zostać zaktualizowany. Porównaj z tym samym kodem, ale używając wnioskowania typu:
auto y = sq(x);
W tym celu intencja jest jasna, y
musi być tego samego typu, co zwrócony przez sq(x)
. Gdy kod zmienia typ zwracany sq(x)
, typ y
zmian 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.