Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Признаки устаревшего языка

Существует большое количество «старых» и «относительно старых» языков программирования, которые не то, чтобы в ходу, а вообще находятся в «мейнстриме» годами и десятилетиями. И не собираются спускаться с верхних строк рейтингов. Но что является признаком устаревания? К примеру, самолёт устарел, если он

  • имеет устаревшую конструкцию, например биплан,
  • изготовлен из «старых» материалов (дерево, полотно, и ряд металлов),
  • имеет неэффективный двигатель,
  • предоставляет низкий уровень комфорта экипажу и пассажирам,
  • имеет низкую надёжность, не эргономичен в управлении,
  • не использует последние достижения науки и техники.
            А что с языками программирования? Понятно, что они не подвержены износу и не знают, что такое «усталость металла». Но ясно, что они тоже могут иметь проблемы, особенно если они разработаны давно, а жизнь, которая никогда не останавливается, накопила опыт решения проблем. А поскольку язык был сделан давно, а опыт появился только недавно, то естественно, что он не учтён этим языком.

            Но старые языки программирования, хоть и остановились в своём развитии, зато обросли «мясом». Библиотеки, фреймворки, среды разработки, масса книг и учебников, тысячи или даже миллионы последователей — вот что имеют старые языки.

Признаки устаревшего языка
            Однако появляются новые языки. Но они, зачастую, ничем не лучше старых. Они ещё не «сошли с конвейера», а уже устарели. Или сошли, и в штампе об изготовлении стоит совсем свежая дата, но... Этот свежий автомобиль имеет устаревшие подвеску и тормоза, у него нет подушек безопасности, движок у него карбюраторный, а салоне — магнитола с кассетами и диапазоном «СВ» и «ДВ».

            Так и язык — он только что вышел из-под пера (простите, клавиатуры) программиста, для него даже тесты ещё не написаны — а он уже устарел. Эх, не получилось никого удивить, вся публика выпячивает губы: «Мы это уже видели».

            Конечно, цели создания языков могут быть разные, например Вы — завсегдатай выставок ретроавтомобилейкомпиляторов и «олдскульных» языков. Эти новые языки, которые лишь хорошо забытые старые, представлены в большом ассортименте в этих списках (разработки наших организаций и частников). Перед этими новыми языками вроде бы ставилась задача пододвинуть старые, но что делать, если они такие же, как и старые, но при этом ещё и «мясом» не обросли? Вот и курят они в сторонке, ожидая, что их компания будет пополнена другими образцами «нового слова в программировании». Такая картина наблюдается не только в родных палестинах, но и в Кремневой долине тоже. Ни Go, ни Swift точно не пошли дорогой революции.

            Рискую повторить классификацию Борхеса, но попробую описать формальные критерии отнесения того или иного языка к устаревшим. И так, каковы они, эти признаки или приметы? Это когда в языке есть:
  • оператор «goto»;
  • такая обработка исключений, которая ещё хуже «goto», когда исключение неизвестно где возникает и неизвестно куда передаёт управление;
  • постфиксные операции «++» и «--», которые для большинства — загадочны;
  • висячий «else»;
  • приведения типов, влекущие «тайное» изменения значения;
  • нулевой указатель и обращения по абсолютным адресам;
  • упор на мутабельные состояния;
  • возможность присвоить неинициализированное значение;
  • визуальный мусор типа «begin» и «end», особенно ЗАГЛАВНЫМИ буквами;
  • синтаксис, прогибающий под себя программистов, а-ля Forth;
  • развитый макроязык, который говорит о неразвитости собственно языка.
И когда в языке нет:
  • ключевых слов а-ля PL/1;
  • приоритетов операций а-ля Lisp или Forth;
  • контроля границ массивов а-ля Си;
  • контроля возможного переполнения при арифметических операциях;
  • функций — объектов первого класса;
  • оператора «for each»;
  • программирования в стиле доказательств;
  • вывода типов;
  • зрительных ориентиров в тексте, позволяющих отличить операции от операндов;
  • синтаксически обособленных чистых функций.
            Если программирование будет идти вперёд, то в том числе через новые языки с новыми подходами и парадигмами. Для того, чтобы оставаться в рамках старых парадигм и привычных подходов, новые языки не нужны. Для этого есть «старый добрый» Си или «тёплый ламповый» Паскаль. Новые Си и Паскаль с иной, пусть и эргономичной, с отшлифованной формой записи проиграют конкуренцию своим первоисточникам.

            Иногда языки могут «выстрелить» благодаря какой-то фишке, которой нет ни у кого. Например, у языка 1С — это русские идентификаторы. У PHP — и ориентированность на Web. Но не раз повторённое новшество теряет притягательность. Однако найти такую фишку при неизменном фундамента программирования сложно.

            Эволюционный путь развития языков «в возрасте» приведёт в итоге в тупик. В языке С++, к примеру, с каждое нововведение увеличивает число правил, усложняет язык. Чем сложнее язык, тем сложнее компилятор. Тем меньшим коллективам он под силу. Тем меньше конкурирующих компиляторов мы будем иметь. При отсутствии конкуренции начнает страдать качество компиляторов.

Опубликовано: 2019.09.05, последняя правка: 2019.09.12    18:48

ОценитеОценки посетителей
   ██████████████████████████████████████████ 2 (100%)
   ▌ 0
   ▌ 0
   ▌ 0

Отзывы

     2019/09/10 10:17, kt          # 

Да, получается так, что «обрастание мясом» (набирание сложности) становится признаком «устаревания». Пишутся возмущенные статьи, что «все сложно», «всего слишком много» и появляется очередной «маленький и простой» новый язык. Когда с новым языком начинают работать по-настоящему, он, естественно сам или через библиотеки начинает усложняться и круг замыкается — нужен опять новый простой и понятный язык. Который вскоре как цыганских детей перестают отмывать и рожают новых и т.п.
Я столкнулся с этим ещё в середине 90-х. В первой прочитанной мною брошюре по Паскалю введение начиналась словами: наконец-то, после «пудовых» описаний PL/1 и ассемблера ЕС ЭВМ, мы получили язык с описанием на нескольких страницах. Года через два наши соседи купили дистрибутив Турбо-Паскаля и упаковка весила (не поверите!) как раз 16 кг. Сам помогал тащить. Основная тяжесть — описание библиотек на хорошей бумаге. Библиотеки — это не язык? Но ведь и в «пудовых» описаниях для ЕС ЭВМ были рекомендации по оптимизации, описание ОС, файловой системы и т.д. А сам язык вполне можно было изложить на нескольких страницах.

     2019/09/10 16:42, MihalNik          # 

В первой прочитанной мною брошюре по Паскалю введение начиналась словами: наконец-то, после «пудовых» описаний PL/1 и ассемблера ЕС ЭВМ, мы получили язык с описанием на нескольких страницах. Года через два наши соседи купили дистрибутив Турбо-Паскаля

Надо понимать, что речь даже может идти о продукции совершенно разных людей. Но, например, и в то время, когда Турбо-Паскаль покупали ваши соседи, и когда Вы ещё читали книгу, в языках у Вирта скобочек begin ... end давно уже не было) Очевидно, удалить их (как и ещё что-то поправить) из турбо-паскаля никакой проблемы для разработчиков не было, вполне можно было выдвигать свои условия к синтаксису языка для закупок ПО.

     2019/09/10 16:48, kt          # 

Так речь не о скобочках, а о возрастании сложности при использовании языка на производстве. "Чистый" Паскаль, Лисп и другие годятся только для школьной информатики. И чем дольше используется язык в реальных задачах, тем больше он обрастает всякими возможностями и дополнениями. А потом дополнениями дополнений.

     2019/09/10 18:36, MihalNik          # 

Так речь не о скобочках, а о возрастании сложности при использовании языка на производстве.

А при чем тут сложность языка? 1с — сложный язык? Нет, это реально старый "бейсик". Программировать на 1с сложно? Да, это требует знания бухучета и кучи соответствующих модулей 1с-а. Но ведь бухучет — это не язык программирования, а прикладная область знания. Делфи сложный язык? Нет, но объектные модели вроде VCL там не маленькие, а это куча английских слов + их назначения и связи м/у ними в программной модели. Ни разу не видел, чтобы кто-то жаловался на добавление цилка "for each" в Delphi или операторов типа "+=" во FreePascal. Программы стало писать проще? Да. Способствует снижению дублирования лексем? Да. Что они там в компиляторе могли чересчур усложнить?
"Обрастание мясом" бычка и "приделывание костылей" к инвалиду — сильно разные явления.

     2019/09/10 21:10, kt          # 

Об этом писал и Автор сайта. Расширения языка просты для тех, кто усвоил язык ещё без них. А тем, кто начинает осваивать с нуля сложнее — они сразу сталкиваются со всем многообразием возможностей. Для тех, кто уже работает с данным языком — процесс его усложнения почти незаметен. Ну появилась ещё одна примочка и хорошо. Обычно понятно, где её использовать. Новичкам все осознать гораздо сложнее. Сравните, как пример усложнения, один из первых учебников по Лиспу (Лаврова) и описания его теперешних потомков.

     2019/09/10 22:25, MihalNik          # 

А тем, кто начинает осваивать с нуля сложнее — они сразу сталкиваются со всем многообразием возможностей.

Никто ж не виноват разрабам, что их компилятор не предупреждает об устаревании конструкций.

     2019/09/12 11:36, Автор сайта          # 

«Обрастание мясом» с большой вероятностью может говорить о том, что язык старый. А если старый, то и устаревший. А вот обратное часто неверно. Если язык не обзавёлся массой библиотек, то это может говорить не о его новизне, а о его непопулярности, у которой может быть много причин.

«Обрастание мясом» — это обзаведение кучей полезных вещей (типа библиотека) вокруг языка, а не в самом языке. От появления библиотек не увеличивается сложность языка, нет необходимости дорабатывать компилятор. «Всё сложно» и «всего много» становится тогда, когда меняют язык и усложняется язык. Документация же может весить 16 кг не к самому языку, который может быть очень мал, а к библиотекам, среде и проч., которые могут быть велики.

"Чистый" Паскаль, Лисп и другие годятся только для школьной информатики.

Если не сопровождаются библиотеками и прочим. А при их наличии они могут применяться много где, и в производстве тоже. Это в PL/1 много всего, что зашито прямо в язык. В других языках можно, не трогая язык, «обрастать мясом».

А вообще весь пафос статьи направлен не на борьбу со старыми конструкциями в старых языках. А на то, чтобы в новых языках не повторяли устаревшие вещи, провоцирующие ошибки и неэффективность. Вот собственная цитата из другой ветки:

Глупо бороться с goto в старых языках. Этот оператор порою предлагает наиболее экономичные решения — в силу правил языка, которые у старых языков уже отлиты в бронзе. Бороться с памятниками — плохая идея. Но в новых языках можно построить правила так, что goto и близко будет не нужен. Однако в них порою предлагаются устаревшие подходы. Вот тогда смотришь на такой язык и приходит в голову классическое: «Молодая была немолода».

     2019/09/15 14:25, Александр Коновалов aka Маздайщик          # 

В статье, как мне кажется, смешиваются два понятия: устаревший и зрелый язык.

Устаревший язык — язык, в основе которого лежат устаревшие концепции, а современные концепции отсутствуют.

Зрелый язык — язык с развитой экосистемой: сообществом, библиотеками, инструментарием. На зрелых языках написаны огромные массивы кода, который должен оставаться работоспособным.

В процессе «созревания» язык неизбежно устаревает — меняются практики программирования, меняется производительность оборудования, появляются новые концепции, осознаются недостатки концепций старых. Конечно, сам язык тоже, как правило, меняется — пополняется стандартная библиотека, вносятся расширения в сам язык. Развивающийся язык «замедляет» своё старение.

В процессе использования выявляются недостатки языка: отсутствие каких-либо средств, многословность некоторых конструкций, отсутствие поддержки какого-либо стиля программирования. И, если язык развивается, то в новых его редакциях добавляются расширения, которые закрывают означенные потребности. Из-за этого «пухнут» зрелые языки.

Но поскольку язык активно используется, расширения должны сохранять обратную совместимость, поэтому максимум что доступно — рекомендовать новые практики взамен старых. Например, в современном C++ не рекомендуются «сырые» указатели (T*), вместо них рекомендуется использовать классы «умных» указателей (std::shared_ptr<T>, std::unique_ptr<T>), а вместо выделения массивов объектов malloc()/new[], нужно использовать библиотечные контейнеры (std::vector<T>, std::list<T> и т.д.)

Устаревшие средства иногда можно удалить из стандартной библиотеки (например, gets() в последних стандартах Си и Си++ удалили), но из ядра уже не удалишь — унаследованный код должен продолжать работать.

Так что любой «зрелый» язык неизбежно будет «старым», т.е. будет допускать возможность писать код по устаревшим принципам. Но есть примеры, когда новая редакция языка предлагает некоторую директиву, которая запрещает в последующем тексте использовать (некоторые) устаревшие средства. Например, "use strict" в современном JavaScript, <!DOCTYPE html> для HTML5. Довольно любопытный способ сохранить «зрелость», избежав «старины».

В комментариях выше написано про килограммы справочников. Действительно, чтобы эффективно программировать на зрелом языке, нужно знать не только синтаксис/семантику (которые ещё и «распухают» при созревании), но и экосистему: библиотеки, среды разработки, хорошие практики программирования. Иначе программист просто не будет конкурентоспособен на рынке. Поэтому программисты вынуждены читать килограммы справочников.

     2019/09/15 19:32, kt          # 

В целом соглашусь.

Например, "use strict" в современном JavaScript

Еще один яркий пример — Фортран. Все исправления — попытки удержаться на плаву (сохраняя огромный задел). Во всех новых текстах обязательно есть директива "implicit none", запрещающая неописанные переменные. Тот самый случай отказа от старого, но сохраняя старые тексты.

     2019/09/15 21:18, Александр Коновалов aka Маздайщик          # 

Visual Basic (классический, VBScript, VBA, не уверен про VB.NET) имеет директиву с похожим именем и точно таким же смыслом — Option Explicit. В BASIC’е раньше тоже переменные неявно объявлялись.

Кстати, о признаках устаревших языков в самом посте. Неявные объявления переменных можно рассматривать как признак устаревшего языка (хотя в некоторых скриптовых языках они могут быть уместны).

     2019/09/16 12:26, Автор сайта          # 

Запрет написания кода по устаревшим принципам по идее должен снимать остроту проблемы устаревшего кода. Однако компиляторы должны должны поддерживать все подходы — и старые, и новые. А это ляжет тяжким грузом на компиляторы.

Неявные объявления переменных можно рассматривать как признак устаревшего языка (хотя в некоторых скриптовых языках они могут быть уместны).

Вообще-то последним словом в этой теме считается вывод типов, внешне напоминающий неявное объявление:
a = 2      // первое присваивание: присвоено и значение, и тип
Тип объекта выводится при первом присваивании. Бонусом является то, что объекту присваивается не только тип, но и значение, т. е. мы не можем использовать объект в правой части выражения до того, как ему будет присвоен тип и значение. Т.е. при выводе типов невозможно использование неинициализированных объектов. А это прогресс, большой шаг вперёд. Однако в определении функций типы должны оставаться.

     2019/09/16 13:06, kt          # 

a = 2 // первое присваивание: присвоено и значение, и тип

А мне это не кажется лучшим решением. Например, в большей части моих задач исходные данные откуда-нибудь читаются и полно переменных, которые вычисляются выражениями, где встречаются и целые и вещественные.
И краткость исходного текста становится каким-то фетишем. Я ведь ещё застал времена, когда при исправлениях вырезали бритвой дырки на перфокарте и заклеивали ненужные.
Тогда старались сделать текст покороче. Я сам использовал букву «Й» для обозначения переменной. Но сейчас экономить на паре строк? Предпочитаю явно указать, что а — это вещественное с мантиссой 53 разряда, чем случайно написать
a=2
вместо требуемого
a=2e0
и получить не обнаруживаемую сразу ошибку

     2019/09/16 18:13, MihalNik          # 

Однако компиляторы должны должны поддерживать все подходы — и старые, и новые. А это ляжет тяжким грузом на компиляторы.

Зачем? Можно выставлять ограничения на время поддержку старых кодов, вплоть до выдачи даты в предупреждениях.

     2019/09/16 18:38, MihalNik          # 

Но сейчас экономить на паре строк?

Избыточная ручная типизация это плохо — может принести к сложности изменений программы из-за неочевидных зависимостей между прописанныыми типами.

     2019/09/16 21:03, kt          # 

Как раз между прописанными типами все зависимости очевидны и не меняются. А если тип зависит от типа присваеваемой константы, вот тогда, как раз и могут при изменениях появится неочевидные зависимости.

     2019/09/16 21:06, Автор сайта          # 

Предпочитаю явно указать, что а — это вещественное с мантиссой 53 разряда

Ну так у «2» есть тип по умолчанию. Если он не устраивает, можно у записать что-то типа
a = long double (2);
Часть же объектов получает тип и значение от аргумента с объявленным типом:
int fun(int x, int y) {
a = x;
. . . }
Ещё одна часть получает тип и значение от функций:
a = f (x);
Везде есть информация о типе. Когда же хочется указать её в явном виде, то в примере
a = long double (2);
это так и делается (так называемая «синтаксическая соль»).

Но сейчас экономить на паре строк?

Дело не столько в экономии, сколько в том, что инициализация типа и значения происходит одновременно. После этого не приходится бороться с неинициализированными переменными. Уходит целый класс ошибок, а это дорогого стоит.

и получить не обнаруживаемую сразу ошибку

Компилятор должен выдать ошибку, обнаружив несоответствие типов. Ведь объекты как-то дальше используются, они же не в вакууме.

Можно выставлять ограничения на время поддержку старых кодов

MihalNik, что-то я не понял этой мысли.

     2019/09/16 23:25, MihalNik          # 

Как раз между прописанными типами все зависимости очевидны и не меняются.

Типы-то как раз меняются, потому что часто слишком жестко привязаны к машинным архитектурам и внешним взаимодействиям.

что-то я не понял этой мысли.

А что тут непонятного? Компилятор выдает предупреждения о необходимости исправления до момента X. После X ругается, требуя правок и/или ссылаясь на старую версию компилятора. Непонятно как раз зачем тянуть десятилетиями дыры и костыли.

     2019/09/17 11:11, kt          # 

Ну так у «2» есть тип по умолчанию. Если он не устраивает, можно у записать что-то типа
a = long double (2);
Везде есть информация о типе. Когда же хочется указать её в явном виде это так и делается (так называемая «синтаксическая соль»).
Дело не столько в экономии, сколько в том, что инициализация типа и значения происходит одновременно. После этого не приходится бороться с неинициализированными переменными. Уходит целый класс ошибок, а это дорогого стоит.

Разумеется, я привык к своему болоту и как всякий порядочный кулик должен его хвалить. И мне такие вещи вроде вывода типа кажутся странными. С моей точки зрения «2» не имеет вообще никакого типа, это заполнение значением. И, кстати, а как по константе помимо типа определить ещё и разрядность (в битах или байтах)?

Например, какую взять разрядность для «а» в выражении «а=0»? Ей-богу, проще самому явно указать и тип, и разрядность напрямую для каждой переменной. Лично мне так и проще, и понятней (я хозяин своих переменных!) Явная разрядность отсутствует во многих современных языках? Ну и зря. Ведь уже нет архитектур с не 8-разрядными байтами. Значит разрядность — универсальная характеристика для выделения памяти.

С неинициализированными переменными тоже задача до конца не решается. Вот в нашей программе куча подпрограмм, из которых по условию выбирается одна. Внутри глобальная переменная инициализируется (во всех подпрограммах разными значениями). Текстуально все в порядке — переменной присваивается значение, а в реальности можно задать условие, при котором ни одна подпрограмма не будет вызвана и нет инициации.

С неинициализированными надо бороться, как 50 лет назад. БЭСМ-6 была 48-разрядной машиной, в каждой ячейке можно было написать или целое или вещественное или 6 символов или 2 команды. Реально БЭСМ-6 была 50-разрядной. Еще два разряда указывали — это данные или команды. При запуске программы память для данных расписывалась этими разрядами и при попытке обратиться к неинициализированной переменной происходило аппаратное исключение (попытка выполнения команд как данных). Видите, у нас полвека назад уже боролись с вирусами по переполнению стека ))

     2019/09/18 11:40, Автор сайта          # 

я привык к своему болоту

Ага, к отеческим гробам, родному пепелищу, а далее по тексту.

С моей точки зрения «2» не имеет вообще никакого типа, это заполнение значением. И, кстати, а как по константе помимо типа определить ещё и разрядность (в битах или байтах)?

Мне видится, что тип «2» должен быть определён как «беззнаковое целое длиною 2 бита». Подобно LLVM IR. А уж потом компилятор решает, сколько байтов должна занять ячейка, хранящая это число.

какую взять разрядность для «а» в выражении «а=0»?

Это «беззнаковое целое длиною 1 бит».

разрядность — универсальная характеристика для выделения памяти.

Полностью согласен.

С неинициализированными переменными тоже задача до конца не решается... можно задать условие, при котором ни одна подпрограмма не будет вызвана и нет инициации.

А конкретнее можно? А то ведь некоторые сторонники goto тоже говорят: «Алгоритм та-а-акой сложный, что без goto не обойтись». Но на поверку оказывается, что точный научный подход может преодолеть любую путаницу. И в случае с неинициализированными переменными можно спроектировать новый язык (старых языков это не касается) так, что они в принципе невозможны.

Еще два разряда указывали — это данные или команды. При запуске программы память для данных расписывалась этими разрядами и при попытке обратиться к неинициализированной переменной происходило аппаратное исключение (попытка выполнения команд как данных).

Может, я что-то путаю, всё-таки я знаком с этой системой только по статьям. Но мне кажется, что там предотвращалось выполнение кода там, где лежат данные. И наоборот, команды могли читать и писать данные, но никак не сами команды. Тогда это другая картина: неинициализированные данные имеют такие же дополнительные (49, 50) биты, что и инициализированные данные. Но я могу и заблуждаться, я с этой техникой не работал.

Но и тут можно увидеть преимущество вывода типов. БЭСМ и «Эльбрусы» увидели бы ошибку только в рантайме, а вывод типов работает уже во время компиляции!

     2019/09/18 15:18, kt          # 

инициализация типа и значения происходит одновременно.

Это при линейной структуре исходного текста. А если стоят ветвления? Например:
if x>0 then a=1; else a=1e-4;

Это «беззнаковое целое длиною 1 бит».

А пользы от такого определения?
Вот в реальной программе:

ON ENDFILE BEGIN; X=0; GOTO ДАЛЬШЕ; END;

GET LIST(Y);
IF Y>0 THEN X=FLOOR(Y); ELSE X=CEIL(Y);
ДАЛЬШЕ:
Чем мучится с пониманием, сколько здесь разрядов нужно под X, не проще ли самому их указать, пусть и с запасом?

неинициализированные данные имеют такие же дополнительные (49, 50) биты, что и инициализированные данные.

Давно было, может тоже память подводит. Но вот как-то так:

Длина слова -- 48 двоичных разрядов и два контрольных разряда (четность всего слова должна была быть "нечет". Таким образом, можно было отличать команды от данных -- у одних четность полуслов была "чет-нечет", а у других -- "нечет-чет". Переход на данные или затирание кода ловилось элементарно, как только происходила попытка выполнить слово с данными).

Четность-нечетность проверялась при ЧТЕНИИ из ячейки. Таким образом, нельзя было выполнить данные и прочитать команды. Память расписывалась командами ЗЧ (кажется) и попытка чтения до записи вызывала исключение.

БЭСМ и «Эльбрусы» увидели бы ошибку только в рантайме, а вывод типов работает уже во время компиляции!

Речь была не о типе, а об инициализации. А здесь анализ при компиляции может ошибку и не увидеть.

     2019/09/19 11:24, Автор сайта          # 

А если стоят ветвления?

Это решаемая проблема. Не в PL/1, конечно, а в новом языке, который можно всё это предусмотреть. Даже с циклами решаемо.

Чем мучится с пониманием, сколько здесь разрядов нужно под X, не проще ли самому их указать, пусть и с запасом?

В LLVM IR так и пишут:
ui1  value;     // величина, под которую необходимо 1 бит
А сколько конкретно будет выделено? Зависит от того, под какую платформу идёт компиляция. Но если есть желание узнать, то для этого есть функций периода компиляции sizeof.

Давно было, может тоже память подводит.

Вот и мне помнится, что в этой архитектуре, что дополнительный бит вовсе не отмечал факт инициализации.

А здесь анализ при компиляции может ошибку и не увидеть.

В функциональной/декларативной парадигме программирования всякого рода переменные состояния задвинуты в угол и маргинализированы. Тут просто другая философия программирования.

     2019/09/19 12:51, Александр Коновалов aka Маздайщик          # 

Вообще-то последним словом в этой теме считается вывод типов, внешне напоминающий неявное объявление:

Подчёркивание моё. Я имел ввиду то, с чем борятся implicit none в Фортране и Option Explicit в Бейсике. В этих языках если где-то используется необъявленная переменная (в любом месте программы), то вместо выдачи синтаксической ошибки компилятор её неявно объявляет. Молча. И, возможно, даже не инициализируя.

В статически типизированных языках, где есть вывод типов, обычно есть оператор объявления переменной. Синтаксис оператора допускает либо указывать тип, не указывая начального значения, либо указывать начальное значение без типа. И этот оператор синтаксически отличается от присваивания. Выглядит это по-разному:
auto pi = 3.142;   /* C++ */
var pi = 3.142; /* C#, Go */
pi := 3.142 /* Go, синтаксический сахар для var pi = 3.142 */
В скриптовом языке Python первое присваивание переменной объявляет её. Это значит, что если используется переменная до первого присваивания, то программа вылетает с синтаксической ошибкой.
print(x) # ошибка
x = 1
print(x) # выведет 1
Это как бы некоторый компромисс между контролем ошибок и динамической типизацией.

А вообще, польза от неявного определения типа может быть там, где эти самые типы довольно многословны. Например, нужно получить откуда-то класс и вызвать у него два метода (псевдокод):
VeryCoolLibrary.Widgets.Window w = globalContext.getMainWindow();
w.setVisible(true);
w.redraw();
Тип для w можно вывести во время компиляции и тем самым сократить код:
var w = globalContext.getMainWindow();
w.setVisible(true);
w.redraw();

Добавить свой отзыв

Написать автору можно на электронную почту mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Каким должен быть язык программирования?

Изобретение очередного велосипеда?

Все языки эквивалентны. Но некоторые из них эквивалентнее других

Признаки устаревшего языка

Лень — двигатель прогресса

О наименовании проекта и языка программирования

Анализ и критика

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее

Последние комментарии

2019/10/15 16:32 ••• kt
Модификация исполняемого кода как способ реализации массивов с изменяемыми границами

2019/10/15 08:58 ••• kt
Типы в инженерных задачах

2019/10/08 01:30 ••• Comdiv
Программирование без программистов — это медицина без врачей

2019/10/07 14:15 ••• Автор сайта
О наименовании проекта и языка программирования

2019/09/19 15:23 ••• kt
Некошерный «goto»

2019/09/19 12:51 ••• Александр Коновалов aka Маздайщик
Признаки устаревшего языка

2019/09/13 16:38 ••• Автор сайта
Программирование исчезнет. Будет дрессировка нейронных сетей

2019/09/12 20:40 ••• Александр Коновалов aka Маздайщик
Циклы

2019/08/30 07:57 ••• Noname
Почему обречён язык Форт

2019/08/29 09:07 ••• рст256
Устарел ли текст как форма представления программы

2019/08/19 19:19 ••• Автор сайта
Шестнадцатиричные и двоичные константы

2019/07/30 14:06 ••• Александр Коновалов aka Маздайщик
К вопросу о совершенствовании языка программирования