Я бачу, що вже є ряд тонких відповідей. Деякі з яких я повторюю, але іноді ви просто хочете викласти речі своїми словами. Я прокоментую кілька прикладів із C ++, оскільки це мова, з якою я найбільше знайомий.
Те, що потрібно, ніколи не є нерозумним. Вибір типу необхідний, щоб інші функції мови були практичними. У C ++ можна мати невідтворювані типи.
struct {
double x, y;
} p0 = { 0.0, 0.0 };
// there is no name for the type of p0
auto p1 = p0;
C ++ 11 додали лямбда, які також не піддаються інтеграції.
auto sq = [](int x) {
return x * x;
};
// there is no name for the type of sq
Введіть також умовиводи, що лежать в основі шаблонів.
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
Але ваші запитання були "чому я, програміст, хотів зробити висновок про тип моїх змінних, коли я читаю код? Хіба ніхто не швидше прочитати тип, ніж думати, який тип є?"
Тип умовиводу видаляє надмірність. Що стосується читання коду, іноді може бути швидше і простіше мати зайву інформацію в коді, але надмірність може затьмарити корисну інформацію . Наприклад:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
Не потрібно багато знайомого зі стандартною бібліотекою для програміста C ++, щоб визначити, що я є ітератором, i = v.begin()
тому явне оголошення типу має обмежене значення. Своєю присутністю він затьмарює більш важливі деталі (наприклад, які i
вказують на початок вектора). Тонка відповідь @amon дає ще кращий приклад багатослівності, що затьмарює важливі деталі. На відміну від використання умовиводу типу надає більшу увагу важливим деталям.
std::vector<int> v;
auto i = v.begin();
Хоча читання коду важливо, це недостатньо, в якийсь момент вам доведеться припинити читання і почати писати новий код. Надмірність у коді робить модифікацію коду повільнішою та жорсткішою. Наприклад, скажіть, що у мене є такий фрагмент коду:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
У випадку, якщо мені потрібно змінити тип значення вектора, щоб подвоїти зміну коду на:
std::vector<double> v;
std::vector<double>::iterator i = v.begin();
У цьому випадку я повинен змінити код у двох місцях. Контраст із висновком типу, де початковий код:
std::vector<int> v;
auto i = v.begin();
І модифікований код:
std::vector<double> v;
auto i = v.begin();
Зауважте, що зараз мені потрібно змінити лише один рядок коду. Екстраполюйте це на велику програму, а умовивід може поширювати зміни на типи набагато швидше, ніж ви можете з редактором.
Надлишок коду створює можливість помилок. Кожен раз, коли ваш код залежить від двох даних, які зберігаються рівнозначно, є можливість помилки. Наприклад, існує невідповідність між цими двома типами у цьому твердженні, що, ймовірно, не призначене:
int pi = 3.14159;
Надлишок ускладнює розрізнення намірів. У деяких випадках умовивід про тип може бути простішим для читання та розуміння, оскільки він простіший, ніж явна специфікація типу. Розглянемо фрагмент коду:
int y = sq(x);
У випадку, коли sq(x)
повертається int
, не очевидно, чи y
є це int
тому, що це тип повернення sq(x)
або тому, що він відповідає операторам, які використовують y
. Якщо я зміню інший код таким, який sq(x)
більше не повертається int
, то з цього рядка невідомо, чи y
слід оновити тип . Контраст з тим же кодом, але з використанням умовиводу типу:
auto y = sq(x);
У цьому намірі зрозумілі, вони y
повинні бути того ж типу, що і повернуті sq(x)
. Коли код змінює тип повернення sq(x)
, тип y
змін автоматично відповідає.
У C ++ є друга причина, чому вищенаведений приклад простіший з висновком типу, умовивід типу не може ввести неявне перетворення типу. Якщо тип повернення sq(x)
відсутній int
, компілятор з мовчки вставляє неявне перетворення в int
. Якщо тип повернення sq(x)
- тип складного типу, який визначає operator int()
, цей прихований функція виклику може бути довільно складним.