Полезные заметки/Список языков программирования

Материал из Викитропов
Перейти к навигации Перейти к поиску

См. Полезные заметки/Языки программирования.

Языки программирования

Выбор языка программирования. Более простая и циничная блок-схема тут.

Автокоды и ассемблеры

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

  • Происхождение названия: assembler = сборщик, откуда взялось «автокод», не известно
  • Автор: разработчик процессора, начиная с Чарльза Бэббиджа
  • Год: как только появляется процессор, появляется и автокод/ассемблер к нему
  • Метод исполнения: компиляция (а точнее, ассемблирование)
  • Типизация: статическая, очень слабая, примитивная
  • Управление динамической памятью: если хочешь, пиши сам
  • Назначение: системное и высокопроизводительное программирование, взлом программ

Автокод — это первый отход от машинного кода в сторону читаемости: каждой операции дано мнемоническое имя, и вместо того, чтобы писать 0E, например, в программе для калькулятора МК-61, мы пишем «В↑» (читается «ввод»). Или на 16-битном x86 можем написать mov ax, [234h] — переместить в регистр ax (двухбайтовый) два байта по адресам 23416 и 23516.

Собственно ассемблер появляется, когда вместо адресов появилась возможность писать читаемые имена — для переменных (вместо mov ax,[234h] мы пишем mov ax, [dataSize]), меток перехода, функций и даже для локальных переменных (последнее — вместо «вершина стека+10»). Далее по ходу компиляции все эти строки будут преобразованы в числовые значения.

Главное отличие ассемблера от других языков программирования заключается в том, что ассемблирование — это прямой перевод текстовых команд на машинный язык, где каждая одна команда ассемблера соответствует одной команде машинного языка, которые будут выполнены в указанном порядке[1]. Другие языки (высокого уровня) позволяют писать строки, выполняющие сразу много математических операций и вызовов других функций, соответственно, компиляция одной такой строки кода сформирует длинный список команд на машинном языке, причём компилятор может записать машинные команды в другой последовательности, если это позволит сократить список машинных команд и повысить скорость выполнения. При этом некоторые ассемблеры имеют на борту препроцессор, с помощью которого можно делать всё то же самое, кроме оптимизации.

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

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

Fortran = Фортран

  • Происхождение названия: FORmula TRANslator, транслятор формул
  • Автор: Джон Бэкус[2]
  • Год: 1957
  • Метод исполнения: компиляция
  • Концепции программирования: изначально линейная память, впоследствии структурное и даже объектно-ориентированное
  • Типизация: статическая, сильная
  • Управление динамической памятью: динамические массивы
  • Назначение: компьютерная математика

Единственный[3] выживший язык из тех времён, «когда компьютеры были большими, а память — маленькой: один бит — один литр». Ничем особенно не интересен, разве что жестоко многословен и приспособлен к перфокартам (одна перфокарта — одна строчка текста).

А жив он по двум причинам: почему-то матрицы в нём традиционно хранятся в памяти в транспонированном[4] виде — не {00, 01, 10, 11}, как в других языках, а {00, 10, 01, 11}. И это неплохо соотносится с кэшем процессора во многих важных преобразованиях матриц.

Вторая причина — на Фортране писали такие корифеи, как Клив Моулер, и потому на нём реализовано очень много подпрограмм компьютерной математики: линейная алгебра, поиск корней уравнений, дифуравнения обыкновенные и в частных производных… Знаменитая BLAS, библиотека линейной алгебры, родом с Фортрана. Огромное количество прекрасно работающего, тщательно вылизанного и проверенного десятилетиями старого кода часто проще и дешевле поддерживать, чем переписывать на более современных языках.

COBOL = Кобол

  • Происхождение названия: COmmon Business-Oriented Language, общий бизнес-ориентированный язык
  • Автор: Грейс Хоппер (в те годы ветеран войны[5], а незадолго до смерти в 1992 штабной адмирал флота США)
  • Год: 1959
  • Метод исполнения: компиляция
  • Концепции программирования: линейная память, принципиально НЕструктурная (а в 2002 году добавили объекты)
  • Типизация: строгая, статическая
  • Назначение: финансы и банкинг

Язык был создан с идеей: «если всё писать максимально близко к человеческому языку (в данном случае к английскому), то программист не понадобится, и любой бухгалтер сможет сам написать всё что нужно». Знакомо, не правда ли? Попытка писать всё естественным человеческим языком провалилась, в том числе и из-за того, что первые нейросети (перцептрон), появившиеся в 1957 году, ещё не умели распознавать человеческий язык (собственно, у них и сейчас далеко не идеально работает функция преобразования написанных «человеческим языком» запросов в работающий код — знают решения ряда типовых задач, но безбожно галлюцинируют на нестандартных задачах и выдают текст, который очень похож на код, но не работает).

COBOL — живой динозавр до сих пор используемый в американских банках, все программисты на котором давно на пенсии.

Язык был раскритикован автором структурного программирования Дейкстрой, автора книги «дисциплина программирования», который сказал про Кобол «Использование Кобола калечит ум. Его преподавание, следовательно, должно рассматриваться как уголовное преступление».

PL/1

  • Происхождение названия: Programming Language One, дословно «язык программирования один»
  • Автор: сообщество SHARE сотрудников IBM
  • Год: 1964
  • Метод исполнения: компиляция
  • Концепции программирования: структурное
  • Типизация: статическая, слабая
  • Управление динамической памятью: несколько способов на выбор
  • Назначение: создать всеобъемлющий универсальный язык на все случаи жизни

Ещё один динозавр, до сих пор живущий на мейнфреймах IBM. Знаменит своей монструозностью из-за того, что создатели пытались впихнуть в один язык абсолютно всё, что тогда было. Язык получился настолько тяжеловесным, что только мейнфреймы тогда его и тянули, хотя по замыслу язык должен был стать абсолютно универсальным и всеобъемлющим.

BASIC = Бейсик

  • Происхождение названия: Beginner’s All-purpose Symbolic Instruction Code, по аналогии с бейсик-инглишем, английским пиджином начала XX века
  • Авторы: Янош/Джон Кемени, Томас Курц
  • Год: 1964
  • Метод исполнения: изначально интерпретация, но возможен любой
  • Концепции программирования: изначально линейная память, впоследствии структурное и даже объектно-ориентированное
  • Типизация: слабая, изначально примитивная, ныне статическая
  • Управление динамической памятью: динамические массивы, позднее сбор мусора
  • Назначение: обучение программированию, некритичное ПО, некоторое время был моден как скриптовый

Основан на синтаксисе Фортрана в качестве учебного языка, подразумевая, что после Бейсика будет легко перейти на Фортран.

Бейсик с нумерацией строк был разработан под консоль-телетайп, когда единственный способ что-то сделать — это набрать команду на машинке и нажать ввод. Строки обычно нумеровались с шагом десять, чтобы, к примеру, между строками 50 и 60 было возможно добавить строки 52, 55 и 56.

Расцвет Бейсика начался, когда Microsoft в лице Билла Гейтса разработал Бейсик для одного из первых хобби-компьютеров — «Альтаир-8800». Практически каждый восьмибитный компьютер имел Бейсик в ПЗУ. Все Бейсики с нумерацией строк имели концепцию программирования «линейная память», и сам язык по своей сути еще долгое время был построен вокруг этой концепции, из-за чего Эдсгер Дейкстра, знаменитый программист и создатель многих ключевых концепций программирования, однажды сказал: «Кто изучал Бейсик, никогда не станет нормальным программистом», имея в виду, что концепция линейной памяти настолько въестся ему в мозг, что структурное и объектно-ориентированное программирование будут от него ускользать.

В 1985 году Microsoft разрабатывает структурный QuickBASIC, но он стал распространён с его упрощённой версией QBasic, пошедшей в состав MS-DOS. Определенной популярностью пользовался также Turbo Basic от Borland, его выгодной особенностью было то, что он являлся компилятором, как QuickBASIC и в отличие от QBasic, который был строго интерпретатором.

Вторую жизнь Бейсик получил с Visual Basic от Microsoft (1990-е). Варианты этого языка существовали много где: Lotus Notes использовал LotusScript, Word и компания использовали Visual Basic for Applications, Windows как таковая (и Internet Explorer) — VBScript, пока его не прижали как небезопасный… И сейчас в наши дни MS Office активно использует VBA, однако планируется заменить его на модный Питон.

Учебные Бейсики разрабатываются и поныне, хотя в более сложном программировании Бейсик уступает место более современным языкам вроде Питона. Отдельного упоминания заслуживает VB.NET: формально это продолжение линейки Visual Basic, но на деле — C#, в котором Си-подобный синтаксис заменили бейсикоподобным; на классический Basic это не очень похоже и с классическим VB ни прямой, ни обратной совместимости не предусмотрено, зато с C# имеется полная двусторонняя конвертируемость кода.

Главная особенность Бейсика, которая пошла ещё с древних консольных времён,— он агрессивно переформатировал код, стирая оставленные программистом средства выразительности.

Pascal = Паскаль

  • Происхождение названия: Блез Паскаль
  • Автор: Никлаус Вирт (Швейцария)
  • Год: 1970
  • Метод исполнения: компиляция
  • Концепции программирования: изначально структурное, впоследствии объектно-ориентированное
  • Типизация: статическая, сильная
  • Управление динамической памятью: ручное (с автоматическим вызовом конструкторов и деструкторов при выделении-отдаче), иногда сбор мусора
  • Назначение: от обучения программированию до сложного ПО 1990-х

Основан на языке Алгол, и Вирт поставил довольно высокую цель: сделать язык, на котором можно работать всю жизнь, от начального обучения до очень сложного ПО тех времён. И, что интересно, это у него получилось! Очень многие игры для DOS написаны на Паскале — за тем исключением, что графическая библиотека Turbo Pascal была медленная и нужно было искать стороннюю. Дальнейшие попытки Вирта развить язык в виде Modula, а затем Oberon, не взлетели: эти языки не набрали популярности Паскаля, а развитием Паскаля стал Delphi (о котором ниже).

По сравнению с Си Паскаль обладал очень быстрой компиляцией (имел полноценные модули и класс LL(1) — считай одну лексему и пойми путь дальнейшей трансляции, и даже многие компиляторы выводили свойственные простым LL(1)-анализаторам сообщения типа «„begin“ expected») и компактной стандартной библиотекой. Так что в Unix, где стандартная библиотека Си лежала где-то в системе, лучшим языком был Си, а за его пределами — Паскаль, пока объёмы памяти не уравняли то и другое. В начале 2000-х подтянулся Си++, а его совсем уж жирная стандартная библиотека стала как-то терпимой.

Этот же LL(1) сделал синтаксис Паскаля несколько более тяжеловесным, чем языков типа Си.

По-видимому, около 1990 компании Borland и Microsoft устроили негласное разделение: Microsoft не будет лезть в Паскаль, а Borland в Си. Но Borland, хоть и разработала сначала отличный Turbo Pascal, а потом отличную Delphi, с 2000-х была всё менее и менее заинтересована в Паскале, пока около 2008 Delphi не приобрела небольшая компания «Амбаркадебра» Embarcadero Technologies. Она наконец сделала две давних задачи для Delphi — Юникод и x64. Но из-за опоздания, постоянной нехватки рабочих рук, странной ставки на кроссплатформенный фреймворк FireMonkey и странных лицензионных финтов Delphi как-то барахтается, но у него нет больше той славы.

Кроме того, Паскаль изначально не имел какой-то автоматики по управлению памятью типа сбора мусора и автодеструкторов, но Borland, делая Delphi, сделала несколько «благословенных» типов, имевших автодеструкторы: новый String неограниченной длины, любой interface, изначально предназначенный для очень классной поддержки Microsoft COM (лучше, чем на любом Си++!), но оказавшийся удобным и для других целей. Новых таких автоуправляемых на Delphi XE4 сделать невозможно. Также некоторые фишки Паскаля — нумерация символов в строке с 1, независимость от регистра букв и другое — на 2000-е были уже устаревшими (вся новая библиотека Delphi нумеровала с нуля). Также сложно встраивать Delphi-подпрограммы в программы на других языках (подпрограммы на других языках в Delphi — проще простого!)

Что в Delphi хорошего и почему он стал таким классным? Языковая поддержка событий Windows, события с замыканием (возможностью передать в обработчик, при каких обстоятельствах его вызвали), близкая к Си++ объектная модель с рефлексией времени выполнения (унифицированное получение и изменение свойств объекта, новый раздел published, для редактирования свойств объекта, автоматической загрузки и сохранения его состояния), достаточно простое создание компонентов и внедрение их прямо в среду программирования.

А ещё Embarcadero известна яростной скупкой всех открытых компонентов, до которых может дотянуться.

Из других кроссплатформенных Паскалей — Free Pascal (и Lazarus, клон Delphi), а также PascalABC.NET.

C = Си

  • Происхождение названия: буква C, как продолжение внутреннего языка B (Би), происходящего от языка BCPL
  • Автор: Деннис Ритчи
  • Год: около 1972
  • Метод исполнения: компиляция
  • Концепции программирования: структурное
  • Типизация: статическая, слабая
  • Управление динамической памятью: ручное
  • Назначение: кроссплатформенные межъязыковые библиотеки, ядра ОС, драйверы, встраиваемый код

Синтаксис с фигурными операторными скобками взят из языка BCPL, ориентация на маленькие буквы — из языка B, его потомка.

Язык Си сейчас не любят из-за нескольких неудачных решений, частично закрытых как в Си++, так и в других языках-последователях: например, зачем ученику для считывания из консоли знать понятие «указатель»? Некоторые функции стандартной библиотеки Си надо вызывать с особой осторожностью, а парочку вообще запретили, их невозможно использовать в безопасной манере и всё! Но всё-таки его влияние огромно, не зря существует целое семейство языков «с синтаксисом Си» (Java, JavaScript, C#, D). И вот что принесло ему такое влияние.

  • Когда компиляторы плохо умели оптимизировать, код типа *(dest++) = *(src++) (переместить данные, находящиеся по одному указателю, под другой, сдвинуть оба указателя на единичку) позволял вручную оптимизировать программу, не теряя в кроссплатформенности! Си позволял оптимизировать низкоуровневый код почти как ассемблер — только кроссплатформенно!
  • Си «паразитировал» на ассемблерных утилитах «линкер» и «библиотекарь». Потому Си вторым после ассемблера приходил на новый процессор. А использование заголовочных файлов вместо модулей — так ассемблер сам таким не брезговал.
  • Си обычно компилирует в знакомые с ассемблера модули, никак не корректирует имена функций и т. д. — потому вызов Си-кода из других языков программирования не вносит никаких побочек. Если язык умеет подключать внешние ассемблерные модули, он подключит и Си[6]. С другими языками приключения могут начаться даже при простой смене компилятора.
  • Препроцессор Си позволил расширять синтаксис под специфичные цели: Windows могла скомпилировать одну и ту же программу и в юникодной версии для Windows NT, и в ANSI для 95. (Впоследствии Windows 98 научилась пускать немалый процент юникодных программ, но всё-таки…)
  • Ну и, конечно, операционная система Unix была написана на Си и имела внутри стандартную библиотеку языка, что давало программам, написанным именно на Си, определённое преимущество над остальными.
  • А если её нет — стандартная библиотека несколько жирнее, чем, например, в Паскале, но не намного. Вся стандартная библиотека для x64 занимает 150 килобайт[7]. По тем временам библиотека была очень функциональной, так что её быстро застандартизировали, и Си был реально кроссплатформенным!
  • Операторные скобки {} были таким достижением, что их приняли даже далёкие от Си языки вроде Rust! Столь же компактно, но по-другому сделал только Питон со своими отступами.

Окончательно Си увело в системную область отсутствие в языке объектов и всего с ними связанного — чтобы «машину» расширить до «гоночной машины», добавив к ней поле «гоночный номер», приходится писать немало кода по абстракции классов и диспетчеризации вызовов, проще перейти на объектный язык. Всё-таки, как сказано в общей статье, объекты очень помогают настольному ПО и играм. Но иногда пишут и на Си: в сетевой библиотеке socket.h поле sockaddr.sa_family — это самая настоящая таблица виртуальных функций. Большинство крупных игр эпохи DOS, включая Dune II, Doom и WarCraft II, были сделаны на Си. (StarCraft и Doom 3 — уже на Си++.)

Forth = Форт

  • Происхождение названия: изначально Fourth (четвёртый), так как автор хотел создать язык для компьютеров четвёртого поколения (с микропроцессором), но затем переименовали в Forth дословно «вперёд»[8].
  • Автор: Чарльз Хэвис Мур (нет, закон Мура был назван не в его честь)
  • Год: около 1971
  • Метод исполнения: компиляция и интерпретация
  • Концепции программирования: упоротая работа со стеком упор на работу со стеком
  • Типизация: статическая, слабая
  • Управление динамической памятью: ручное
  • Назначение: сейчас используется преимущественно в микроконтроллерах, где нужна компактность и интерпретатор на борту[9].
  • Особенности: простейшее правило трансляции (слова разделенные пробелами), благодаря чему свою реализацию форта можно реализовать на чём угодно, была бы необходимость. «Проще» реализация только в языках K и J, где трансляция ведется посимвольно.

Forth — если не считать ассемблера, то единственная альтернатива C тех времён, когда требовалась высокая скорость и максимальная компактность, и было физически невозможно запустить на микроконтроллере C++ как это делают в наши дни. По этой причине, язык не сказать, что полностью помер, но почти везде практически вытеснен, даже, не C, а C++, поскольку объём памяти большинства современных микроконтроллеров позволяет на них запусть DOOM, и как следствие, крайне редко бывает необходимость жёстко экономить ресурсы и писать на Форте.

Отличается особой формой записи – т. н. обратной польской нотацией выглядевшей как функциональный язык наоборот и абсолютно без скобок, то есть конструкция mul(add(2,3),5) на нём выглядит как 5 2 3 + *. Из-за этого и пошли шутки, что «Речи странной Йоды магистра секрет раскрыт — на Форте просто программист он старый».

C++ = Си++

  • Происхождение названия: Си и операция «прибавить единичку»
  • Автор: Бьёрн Страуструп (наиболее распространённая транскрипция) / Бьярне Строуструп (так по-датски)
  • Год: 1983
  • Метод исполнения: компиляция
  • Концепции программирования: структурное, объектно-ориентированное, немножко функциональное, немножко декларативное, и вообще засасывает всё из соседних языков[10]
  • Типизация: статическая, слабая (но везде, где не нужна совместимость с Си, гайки прикручены по максимуму)
  • Управление динамической памятью: ручное, автодеструкторы
  • Назначение: крупное критичное к скорости ПО

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

  • Автодеструкторы и исключения! Оказывается, программирование — это кодирование алгоритмов, а не механическое набивание 100500-го if(errno) {free(a); free(b); free(c); return FALSE;}. Батарею free в обработчике ошибок выполнит деструктор, а сообщение об ошибке кинет дальше механизм исключений. Программы на Си++ при минимальной дисциплине программирования почти не «текут» (редко случается ошибка утечка памяти, когда динамическая память выделяется и не освобождается).
  • Шаблоны! Написав объект, например, «список», мы сразу же получаем «список целых», «список строк», «список врагов в игре», несовместимые друг с другом. Были добавлены в язык в 1991 году.
  • Самый проработанный механизм расчётов прямо при компиляции. Для числовых расчётов достаточно дополнить код парой ключевых слов, и он уже вычисляется при компиляции, а в исполняемый код попадут заранее рассчитанные результаты, для массивов и строк посложнее. Можно, скажем, приделать к неизменяемому списку данные для быстрого поиска.
  • Ну и препроцессор Си, который ничем не изменился, но вместе с синтаксисом Си++ получил новую жизнь и позволяет написать, например, очень красивое модульное тестирование. Или механизмы совместимости, чтобы как-то жить в зоопарке «много-много». Посмотрите на макросы совместимости в большой старой библиотеке, скажем, для Delphi и Си++ — и поймёте. А ведь Delphi — это «линейка-много».

«Из коробки» Си++ имеет типы «строка произвольной длины», «линейный список» и ещё много другого — и «благословенные» (то есть интегрированные в синтаксис языка и/или архитектуру процессора) среди них лишь отдельные маленькие и простенькие[11], всё в теории пишется и на чистом Си++! Так что почти всю эту мега-библиотеку при желании можно выкинуть, чтобы притащить свою: как любят говорить в Си++, «ты не платишь за то, что не заказываешь».

С такими возможностями «си с крестами» просто создан для игр и настольного ПО. Все эти виртуальные машины со сбором мусора, скорее всего, написаны на Си++. Если и создают другие языки — то чтобы закрыть его недостатки, коих откровенно много.

  • Та самая противная медленная компиляция. Это связано и с особенностями синтаксиса, и с широким использованием шаблонов, и много с чем ещё.
  • Очень тяжеловесный синтаксис из-за всех этих шаблонов, некоторые из которых — или костыли, или редкая функциональность[12].
  • Шаблоны позволили очень многое и даже больше. Но и тестирование шаблонов на работоспособность — проблема, механизм концепций (2020) для всего этого позволил закрыть хоть простейшее.
  • В библиотеке есть много неудачных мест: написать свой поток (штука, напоминающая файл, только работающая не с файлом, а с куском памяти, архивом, сетью…) — та ещё попоболь.
  • Не полная, но изрядная совместимость с Си, которую всё ещё тянут.
  • Поскольку стандартные структуры данных обычно появляются по просьбам трудящихся, а свои пишутся без вопросов, процветает «велосипединг», особенно в больших старых библиотеках: если мы имеем дело с фреймворком Qt, скорее всего нам потребуется строчка и стандартная, и встроенная в Qt.
  • Ну и стандарты безопасности ныне другие. Так, браузер Firefox переписывается на Rust, краеугольный камень которого — не допускать обращений к посторонней памяти на уровне языка, но не собирать мусор, давая скорость и компактность как у Си++.
  • Комитет по развитию C++ постоянно критикуется за то, что вместо решения реальных и давно назревших проблем языка (особенно шаблонов), увлечён добавлением очередных свистелок и перделок, превращая язык в монстра, сравнимого с легендарным PL/1.

Python = Питон, Пайтон

  • Происхождение названия: Monty Python (но очень часто иконки рисуют какую-то змейку)
  • Автор: Гвидо ван Россум
  • Год: 1991
  • Метод исполнения: интерпретация[13]
  • Концепции программирования: структурное, функциональное, объектное
  • Типизация: динамическая, прототипная, слабая
  • Управление динамической памятью: сбор мусора
  • Назначение: обучение программированию, скриптовый язык для всего, «продвинутые командные файлы», серверный веб, компьютерная математика, некритичное ПО

Отличительная черта питона — это упрощенный синтаксис. Ни тебе скобочек фигурных, ни точек с запятой, ни сволочей разных. При этом вложенность блоков определяется отступами в коде, из-за чего волей-неволей формируется культура программирования, иначе просто не запустится. Разрабатывался как очень продвинутый скриптовый язык и потихоньку расширялся классическим «великодушным пожизненным диктатором» открытого сообщества. Как и многие другие скриптовые языки, интерпретатор Питона позволяет на манер Бейсика писать по строчке и исполнять их (т. н. система REPL).

Изначально он был классическим скриптовым языком с динамическими объектами, но к 2000 Питон обзавёлся полноценными объектами и мусорщиком, как в Java. Питон обрастал и обрастал функциональностью, и вдруг полюбился в компьютерной математике (Россум сам работал в институте преподавателем программирования). Исследователям в принципе не нужно делать качественные программы, и язык с фривольным синтаксисом оказался к месту. Вторая причина — код y = math.sin(x) по факту шаблон: он работает и для одной цифры (получается синус), и для массива (получается такой же массив из синусов), и для штук поинтереснее вроде автоматического дифференцирования (получается формула в компьютерном формате — правда, вместо math модуль берут другой), это оказалось очень удобным в численных методах.

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

В 2008 вышел не полностью совместимый Питон версии 3, но неожиданно оказалось, что второй версии написана огроменная куча софта, переписывать которую на третью версию мало кто решился. К 2020 полный переход сделали (до этого некоторое ПО держало обе версии).

Всё чаще Питон используется как встраиваемый скриптовый; Питон-скрипты поддерживают Inkscape (векторный редактор) и FontForge (редактор шрифтов).

Хороший язык, разве что сложное ПО делать подчас трудно, как и на любом другом интерпретируемом языке. Но реально, ведь для всех крупных библиотек есть Питон-обёртки. Не удивительно, что в блок-схеме в начале статьи 7 исходов из 23 — это Питон.

Java

  • Происхождение названия: сорт кофе (якобы любимого напитка программистов) + «язык должен работать даже на кофеварке»
  • Автор: Джеймс Гослинг, Sun Microsystems
  • Год: 1995
  • Метод исполнения: промежуточный код
  • Концепции программирования: объектно-ориентированное, немножко функциональное
  • Типизация: статическая, сильная
  • Управление динамической памятью: сбор мусора
  • Назначение: серверный веб, программируемость в некоторых средах вроде Java ME и Android

Имеет огромную армию хейтеров при сравнимой армии фанатов. Принесла в программирование очень много — промежуточный код, сбор мусора и несколько концепций программирования, о которых позже. Пытаясь придумать интерпретатор прикладных программ и даже простых игр для слабого процессора, Гослинг столкнулся с такими вопросами.

  • Процессор-то слаб — так что максимум работы было переброшено на машину разработчика, а программа распространялась в виде промежуточного кода. Интерпретатор напоминал архитектурой процессор и получил прозвище виртуальная машина.
  • Хотелось бы нормальную динамическую память, чтобы на том же слабом процессоре просто пройти по ссылке, а не искать объект в словаре — потому из пыльного угла достали сбор мусора.
  • По любому прогерскому неверному чиху программа должна «упасть» с ошибкой (как на этапе компиляции, так и на этапе исполнения), а не пытаться гадать, чего там программист захотел. Скажем, каждая подпрограмма должна наперёд заявлять, какие ошибки она может выбрасывать. Ошибки поделили на три типа: ошибка программиста (обратился к 20-му элементу из 10), аномалия времени выполнения (ошибка ввода-вывода, пропала сеть) и полный крах (что-то нехорошее в виртуальной машине), заявляются только вторые. Впоследствии эта практика подтвердила свою порочность: на веб-сервере та же ошибка ввода-вывода ничем не отличается от полного краха. А иногда мы вызываем чужой объект неизвестного устройства и не знаем, какие ошибки он может генерировать: выдернули флэшку? пропала сеть? ошибка в базе данных?

Так же, как и на Си++, почти всю библиотеку реально написать на Java, но «благословенных» типов довольно много: всё, что начинается на java.lang, как-то привязано к языку: строки, ошибки, информация о типах.

В любом языке с наследованием есть вопрос: наследование от одного класса слишком ограничивает, а наследование от двух — что будет, если дважды разными путями унаследоваться от класса X (проблема ромба)? Выяснилось, что почти гарантированно будет плохо, когда дважды наследуются изменяемые данные (независимо от того, они дублируются или есть механизмы антидублирования), и иногда меньшие глюки — когда разные пути наследования написали разную функциональность. Java на уровне языка сделала несколько ограничивающую, но в целом удачную и повторённую в C#, Delphi и ещё много где объектную модель: наследоваться можно от одного класса, но есть дополнительная сущность интерфейс, грубо класс, не имеющий ни данных, ни функциональности, только заголовки функций, и от интерфейсов можно наследоваться неограниченно (реализовать интерфейсы). Следите за руками: данных в интерфейсе нет, дважды реализуем один и тот же интерфейс — обе реализации равносильны. В Java 8 в интерфейс добавили эталонную реализацию функции[14], но реализация, сделанная классом-предком, всегда предпочтительнее: он зачем-то перекрыл именно её, эталонную. Даже в Си++ стараются наследоваться именно так.

Около 2000 Microsoft с их Visual J++ заметили за их фирменной практикой «embrace, extend, extinguish» — поддержи (и стань лидером), расширь, перепиши расширение на совсем другой технологии, конкурент загнётся. После суда Microsoft отказалась от Java и создала C#, выпустив напоследок ещё и J#.

Где-то около 2004 Java научилась частично компилировать в машинный код и стала довольно быстрой. Тогда же придумали интересный способ поддерживать не только «список общего вида», но и «список строк», и «список врагов в игре» — дело в том, что все объекты хранятся в динамической памяти и доступны только по ссылкам. Внутри под капотом это список ссылок общего вида, несовместимость обеспечивается на уровне компилятора. Такие «недо-шаблоны» оказались значительно проще для программиста, чем в Си++.

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

Существуют несколько профилей Java (Standard edition, Enterprise edition, Micro edition, Card) — они отличаются только набором библиотек, а также способностью или неспособностью поддерживать дробные числа.

Java Micro Edition была распространена повсеместно, несмотря на жуткую фрагментацию: у мобильника, извините, есть определённое разрешение (от 101×80 до 320×240), да и памяти на игру немного, от 200 килобайт до мегабайта. Без задела по всему — памяти, процессору, размеру архива[15], разрешению экрана и т. д. — игру практически невозможно сделать независимой от разрешения на манер Hollow Knight, к тому же совсем не стандартизировали коды кнопок (а ведь были телефоны с перьями, тогда ещё резистивными), плохо и поздно стандартизировали мультимедиа. Потому любая игра имела два-три десятка архивов под разные телефоны. Некоторые телефоны могли гонять игры с других платформ: Sony Ericsson поддерживали JAR’ы от Nokia. Но как сейчас определённая прослойка людей заносит чемоданы денег в какую-то гачу, так тогда покупала Java-игры.

Новую жизнь Java принёс Android — их виртуальная машина далека от Java, но язык бережно сохранили «и вообще нам ни с чем не надо обеспечивать совместимость, у нас своя система» — так что Google хоть и судился с алчной Oracle (поглотившей Sun), но выиграл по очкам. Этот выигрыш в тяжбе, длившейся одиннадцать (!) лет, подтвердил: посторонняя реализация программного интерфейса является добросовестным пользованием и не нарушает авторских прав. Да и что было бы, если бы производитель какого-то коммерческого Unix засудил POSIX…

Существует множество языков, работающих с виртуальными машинами Java (Kotlin, Vala, Clojure), о них не будем.

Сборщик мусора, неожиданно вмешивающийся в работу программы, вызывая раздражающие тормоза при простейших действиях (решив, что раз программа не сильно нагружена, то самое время заняться сбором мусора, а пользователь может и подождать), создал знаменитые мемы «Джава не тормозит» и «прогрев Джавы», а также искусственные тесты, когда сначала ждут прогрева виртуальной машины, и только затем начинают тест скорости работы программы, а если во время теста неожиданно сработал сборщик мусора, то это «несЩитово! нужно сначала дождаться прогрева».

JavaScript

  • Происхождение названия: Java как buzzword[16] + script
  • Автор: Брендан Эйх
  • Год: 1995
  • Метод исполнения: интерпретация
  • Концепции программирования: объектно-ориентированное, функциональное
  • Типизация: слабая, динамическая, прототипная, легендарно неразборчивая
  • Управление динамической памятью: динамические объекты
  • Назначение: веб (как клиентский, так и серверный)

Интерпретируемый язык с несколько непоследовательной динамической типизацией, когда 2+«2»=«22», а «22»−2=20: операции над данными возможны между любыми типами, но предсказать, что при этом получится, порой бывает трудно. В отличие от VBScript, потомка Visual Basic, JavaScript никак с Java не связан, а лишь похож синтаксисом, унаследованным от Си. Изначально язык назывался Mocha, затем Live Script, а Netscape, чтобы воспользоваться популярностью Java, переименовала его в JavaScript. Получил огромное распространение как язык клиентского веба: любой браузер может работать как интерпретатор JavaScript, и поэтому JavaScript работает везде. Хотя пытались на нем писать и вещи, не имеющие прямое отношение к вебу, и даже игры.

Во время войны браузеров JavaScript у разных производителей даже имел разные библиотеки, но с падением Internet Explorer как-то смогли его стандартизовать. Большую роль в этом сыграли тесты Acid — в версиях 1 и 2 они проверяли движок вёрстки браузера, а в версии 3 — в первую очередь JS. А пока Internet Explorer мучительно умирал (2008) и любое решение Microsoft — и оставить совместимость, и порвать — будет встречено в штыки, Спольский и написал ту самую эпохальную статью про марсианские наушники.

Из-за несколько тяжеловесной работы многих вещей «из коробки» JS известен своими многочисленными фреймворками, некоторые из которых, как TypeScript (попытка приделать к JS строгую типизацию), тянут на вполне себе отдельный язык.

Распространённый ныне формат данных JSON — это JavaScript Object Notation. Истоки просты: чтобы не разбирать формат данных, пришлём данные прямо в формате языка, соберём скрипт и исполним его. Поскольку веб — это львиная доля современного программирования, а единственный недостаток формата — для него невозможно наладить потоковый разбор[17] (то есть разбор по кусочкам, когда занимаемый объём значительно меньше, чем огромный набор данных), JSON расползся по всему программированию.

Поскольку клиентский веб всё больше и больше зависит от JavaScript, то Google и Firefox сделали высокопроизводительные (и даже компилирующие в машинный код!) движки. Эти движки предложили в качестве скриптовых машин общего назначения, но прижились они на веб-серверах — Node.js.

C# = Си-шарп

  • Происхождение названия: язык Си, к которому добавили диез, так что нота C♯ (си-шарп) — это нота «до-диез» между нотой C («до») и D («ре»)
  • Автор: Андерс Хейлсберг (автор Delphi и Visual J++, а также фреймворка TypeScript для JavaScript)
  • Год: 2002
  • Метод исполнения: промежуточный код
  • Концепции программирования: объектно-ориентированное, слегка функциональное
  • Типизация: статическая, сильная
  • Управление динамической памятью: сбор мусора
  • Назначение: различное ПО для Windows, как настольное, так и серверное; мелкие игры (в том числе кроссплатформенные)

Ответ Microsoft на Java после отказа от Visual J++ по результатам суда, разработанный при участии одного из авторов Delphi. Название прямо намекает на развитие C++. Причём Microsoft в том же 2002 году, когда вышел C#, успела выпустить напоследок ещё и J#. Система исполнения имеет странное название .NET.

Язык устроен логичнее, чем Си. Объектный синтаксис приделали ко всему, включая числа, что-то вроде pi.sin(). В отличие от Java, объекты-значения бывают и пользовательские, что позволяет меньше грузить мусорщик в необъектном коде, ограниченно разрешён «опасный» код — в общем, с производительностью заморочились серьёзно.

В третьей версии добавили LINQ, позволяющий писать в стиле SQL.

На C# и других языках для .NET любят писать мелкое ПО для Windows — из-за простоты программирования, крайней безопасности и небольшого размера дистрибутива (.NET ведь давно в Windows).

Главный недостаток — привязка к инфраструктуре Microsoft (даже исполняемый файл называется *.EXE) и очень далёкий «от железа» кроссплатформенный интерфейсный фреймворк WPF = Windows Presentation Foundation (некроссплатформенные Windows Forms сделаны образцово). А на что нужен за пределами Windows язык с таким интерфейсом? Так что хоть и сделали Mono, кроссплатформенную версию .NET, вне Windows она используется в основном для мелких игр. (В любой игре на впечатления влияет не средний FPS, а микролаги или запинки, и если нет запаса по производительности и специальных методик программирования, снижающих нагрузку на мусорщик[18], сбор мусора — важный источник этих запинок.)

Для игр существуют движки XNA (полностью на C#) и Unity (сам движок на Си++, но рабочим предлагается C#).

Rust = Раст

  • Происхождение названия: Rust, дословно «ржавчина», в честь Rust Fungi — «ржавчинных грибов» с очень сложным жизненным циклом из пяти жизненных форм, что восхитило автора языка как пример «переусложнения для выживания»
  • Автор: Грэйдон Хор (сотрудник Mozilla, который и переписал на Расте браузер Firefox)
  • Год: 2015
  • Метод исполнения: компиляция
  • Концепции программирования: функциональная с кастрированным в целях безопасности ООП
  • Типизация: статическая, сильная
  • Управление динамической памятью: автоматическая гарантирующая безопасность работы с памятью
  • Назначение: замена C++, гарантирующая безопасность работы с памятью

Rust — cамая удачная замена C++[19], но с существенными недостатками для полной замены https://habr.com/ru/articles/813139/

Проблемы ООП в языке решены методом «серпом по яйцам» со всеми вытекающими[20].

1С = Один-Эс

  • Происхождение названия: от названия программы. Сама же программа — от «одной секунды», столько должен идти средний поиск на среднем 80386
  • Год: 1993
  • Метод исполнения: промежуточный код
  • Концепции программирования: процедурная
  • Типизация: динамическая
  • Управление динамической памятью:
  • Назначение: бизнес-приложения

Язык программирования для написания бизнес-приложений (конфигураций) на платформе «1С: Предприятие» (строго проприетарный, платформа необходима для работы промежуточного кода). Характерная особенность — все ключевые слова на русском языке (синтаксис сильно напоминает Basic, переведённый PROMT’ом). Английский язык тоже поддерживается, но им почти не пользуются: программа «1С: Предприятие» не получила распространения за пределами России и ряда сопредельных стран, в основном бывших республик СССР — она создавалась под постсоветское законодательство в области бухучёта и документооборота, и за пределами СНГ-шного правового поля просто не востребована.

Примечания

  1. Справедливости ради, одном мнемонике может соответствовать несколько инструкций. Например, на х86 для некоторых команд есть "облегченные" варианты с использованием регистра AX/EAX/RAX, которые игнорируются ассемблером. Так что даже при использовании языка ассемблера не всегда можно говорить о прямом переводе
  2. Известный понятием «бэкусовская нормальная форма» — метод записи синтаксиса компьютерных языков. Лауреат Тьюринговской премии, если что — компьютерного аналога Нобеля.
  3. Строго говоря, есть еще и Кобол, который сохранился до нашего времени за счет своего статуса «американского 1С», то есть языка, на котором написаны многие бизнес-приложения в США, и даже ещё более многословен.
  4. Первый курс института. Транспонирование матрицы — это такой поворот, что строки превращаются в столбцы, а столбцы — в строки.
  5. Непосредственно в боевых действиях Второй Мировой участия не принимала, а как профессиональный математик занималась артиллерийскими расчётами на компьютере Mark I для флота США.
  6. Разве что иногда нужно свести языки по соглашениям вызова, поднастроив код на Си или на принимающем языке.
  7. MinGW 14.2 для Windows x64.
  8. Произносится языколомно [fɔːrθ] (британский вариант произношения ещё языколомнее [fɔːθ]), а «форт» — это транслитерация, а не транскрипиция
  9. Как и остальные языки, может использоваться для любых целей. Например, на нём запилен аналог cron для винды.
  10. Однажды даже сбор мусора (опциональный) предложили — но ни один из компиляторов его не реализовал, и десять лет спустя тихонечко выкинули.
  11. Например, atomic — атомарные (корректно работающие в многозадачной среде) операции с числами, используемые для управления этой самой многозадачностью.
  12. Пример костыля: в 2014 году упростили std::is_trivial<int>::value → std::is_trivial_v<int> — и поныне свойства типов кончаются на _t (если это тип) и _v (если это значение). Редкая функциональность: у строки basic_string<Char, Traits, Allocator> три параметра: Char (из чего строка), Traits (особенности типа) и Allocator (как выделять память). Последние два крайне редко нужны нестандартные.
  13. существуют реализации с возможностью компиляции.
  14. Связано это с развитием библиотеки: интерфейс расширили, а старый код новые функции не реализует. Но удобно и для программистов, пример: пусть у нас есть «поток данных» (типа-файл, но работающий с устройством или архивом), и у него есть функция remainder() (получить, сколько ещё байтов осталось за кареткой). Подавляющее большинство пользовательских потоков работает с данными, как-то сжатыми или закодированными (а не с периферией), и для них годится эталонная реализация remainder() = size() - position(). А вот общее количество данных size() и положение каретки position() должен писать наследник. Бывают потоки, где вместо size() и position() затычки (например, живые данные с какого-то устройства), а remainder() можно придумать другой, неэталонный (заглянуть в буфер ввода, сколько там ждёт байтов). Но в любом случае эталон должен иметь правдоподобно-законченный вид, писать в интерфейсе незаконченную функциональность — моветон.
  15. Так называется дистрибутив Java-программы: это ZIP-архив с расширением JAR (Java ARchive).
  16. Прожужжавшее уши слово, которое потеряло значение из-за неумеренного употребления посторонними, рекламой или пропагандой. Примеры из разных областей: эксклюзивный (только для вас и больше ни для кого → какой-то крутой), демократия (доступ народа к управлению → захват власти «кем надо»), искусственный интеллект (методики, имитирующие работу мозга, когда даже сам разработчик не знает, почему оно работает → любая нетривиальная автоматика).
  17. Существуют три подхода к разбору универсальных форматов данных XML и подобных: событийный, потоковый и объектный. Событийный — библиотека читает внешним циклом, программа реагирует (очень быстр, но сложности отданы программе, используется отдельными мазохистами). Потоковый — программа внешним циклом инициирует чтение куска, библиотека читает, программа разбирает, что прочиталось (почти так же быстр, сложности отданы библиотеке, основной на больших объёмах). Объектный — библиотека воссоздаёт структуру XML/JSON в памяти, программа читает эту память (метод прост, на нём написаны как самые медленные, так и самые быстрые реализации, наименее склонен к ошибкам, основной на малых объёмах, один недостаток: требует памяти в разы больше, чем XML/JSON занимает на диске). Деление на атрибуты и тэги сильно упрощает разбор XML: никто не кладёт большие — а тем более неограниченно большие — объёмы данных в атрибуты.
  18. Кто умеет программировать, гуглите «объектный пул».
  19. Другие альтернативы Swift от Apple и Go от Google — получились более нишевыми; для сравнения D — тоже продвигавшийся как альтернатива C++ не обрёл даже узко нишевой популярности.
  20. ещё более кастрировано ООП в Go, которое тоже продвигают как альтернативу C++