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

TL;DR: выборка из переписки об изучении нового языка программирования (ЯП).

Grigory, [16.12.20 21:01]

Любой ЯП определяется следующими своими свойствами:

  1. Сложность по Тьюрингу. Всё, что слабее машины Тьюринга, нас не интересует.
  2. Система типов (какие есть базовые типы, как делаются производные типы, какие проверки когда делаются)
  3. Система выделения ресурсов (какие есть классы хранения для переменных и констант, как определяется и кем контролируется время жизни объектов)
  4. Объём синтаксического сахара, который нужно зазубрить, чтобы считать себя профессионалом
  5. Как устроены принципы расширения и переиспользования функциональности
    4.1 Объём и полезность стандартной библиотеки, поставляемой с языком
    4.2 Кипучесть жизни сообщества, создающего и поддерживающего остальные библиотеки
  6. Как язык работает с исключительными ситуациями

Примеры того, как некоторые ЯП ложатся на эту систему.

Ассемблер

  1. Удовлетворяет.
  2. Нетипизирован. Есть один тип данных — сырые числа.
  3. Все ресурсы управляются вручную, или же описаны в ABI (то есть вне языка)
  4. Относительно небольшой. В лучшем случае есть: секции, макросы, комментарии, псевдотипы данных
  5. Не определяются языком, в лучшем случае тулчейном для него.
    4.1 В лучшем случае доступно то, что есть в API/ABI операционной системы или через сервисы EFI/BIOS.
    4.2 Обычно только то, что сам написал. С другой стороны, если уж пишешь на ассемблере, то умей подключать либы, написанные на других ЯП.
  6. Язык обычно не определяет механизмов для обработки ошибок. Эти механизмы прописаны в ABI и/или в архитектуре ЦПУ.

С++

  1. Удовлетворяет
  2. Традиционные скалярные примитивные типы в наличии. Статически и динамически типизирован.
  3. Есть следующие классы: константы, автоматические переменные, динамические переменные. Управление ресурсами ручное.
  4. Просто дохуя сахара, и его только прибавляется.
  5. Удивительным образом, до сих пор не определён в языке. Всем понятно, что это ЁБАНЫЙ СТЫД в 2020 году.
    4.1 Хороший объём и полезность. STL решает много проблем
    4.2 Большое сообщество. Однако см. пункт о библиотеках, что портит жизнь значительно.
  6. Механизм исключений (опциональный)

Язык Markdown

  1. Не Тьюринг-полный. Это же язык разметки

Питон

  1. Удовлетворяет
  2. Базовые скалярные и контейнерные типы в наличии. Динамически типизирован. В версии 3.9 появились необязательные аннотации статических типов.
  3. Один класс хранения — динамически аллоцируемые данные. Автоматическая сборка мусора.
  4. Приемлемое количество сахара. Его объём медленно растёт.
  5. Изящная система модулей. Не без косяков.
    4.1 Принцип Питона — batteries are included. В стандартной либе есть очень много полезного.
    4.2 Современная система пакетов и систем для управления ими.
  6. Механизм бросания/перехвата исключений.

Java

  1. Удовлетворяет
  2. То же самое, что С++ и Питон.
  3. Примерно как Питон. Автоматическая сборка мусора.
  4. Адекватное количество сахара.
  5. Нормальные модули, стандартная либа и сообщество.
  6. Механизм бросания/перехвата исключений.

Исключения из нормы

  1. Язык Lua — в системе типов нет целых, только с плавающей запятой. Очень неудобно для некоторых доменов применения.
  2. Язык Perl — объём сахара просто зашкаливает и, наверное, побивает в этом С++.

Зачем всё это

Почему это важно?

Новички в каждом языке много времени тратят на пункт 3 (синтаксис). На практике же достаточно изучить подмножество, достаточное для написания Тьюринг-полных программ (т.е. знать как сделать цикл), а остальное учить по пути.

Классы хранения могут стать непреодолимой преградой для довольно большого числа людей. Известно, что только доля населения Земли в состоянии освоить концепцию “указатель на переменную”. В этом плане языки с управляемой памятью являются для них единственным выходом.

После освоения ядра языка всё остальное время проводится в поиске и переиспользовании уже написанного кода. Поэтому пункт 4 важнее всех остальных вместе взятых.

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

Примеры: для JVM есть несколько языков, которые все используют общие либы https://en.wikipedia.org/wiki/List_of_JVM_languages. То же самое для .NET: https://en.wikipedia.org/wiki/List_of_CLI_languages

То есть например можно реально забить на весь сахар языка С# и писать на любимом тебе Бэйсике, и всем от этого будет нормально.

Успех ЯП в 21 веке определяется объёмом библиотек, доступных для него, и интероперабильностью его с другими языками.

Классы хранения?

Пример из С++:

enum {
     i_am_literal = 1234
};
static int v1 = 0;
static const char *str = "hello";

void main()
{
    char auto_var = 56;
    double *p_d = new(double);
}

В этом примере i_am_literal — литерал, v1 и str — статические, имеют время жизни, равное времени жизни программы. Затем, auto_var — автоматическая переменная, живёт, пока не закончится окружающий её блок {}.

Наконец, *p_d — динамическая переменная. Время жизни данных, на которые указывает *p_d, определяется программистом. Если он не позовёт delete(), то память утечёт.

В Питоне, Джаве и других языках все переменные одного класса хранения. Занятая ими память освобождается без прямого контроля со стороны программиста. В таких языках нет указателей. В таких языках все переменные — это ссылки. Есть исключения, конечно, но сейчас не о них.

[Я упрощаю про Джаву, но для Питона это верно]

Ещё проще

Если ещё проще, то изучение нового ЯП для меня — это понимание, как в нём делаются следующие вещи:

  1. Декомпозиция
  2. Абстракция
  3. Работа со скучными проблемами

Пункты 1 и 2 влияют на то, как решать сложные задачи, а 3 — как не сойти с ума от ежедневной рутины.


Written by Grigory Rechistov in Uncategorized on 17.12.2020.


Copyright © 2020 Grigory Rechistov