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

Сейчас я решил продолжить дискурс и перенести его в практическую плоскость. Я сделал форк CPython и попросил DeepSeek немного поиграться с синтаксисом. Хорошо, что в питоне обновили парсер — он теперь достаточно гибкий.

В общем, если смотреть с формальной стороны — получился новый язык. Он немного расширяет питон (то есть, является суперсетом), но совсем чуть‑чуть. Оставаясь при этом верным главному синтаксическому принципу — значимым пробелам. Целевые рантаймы для этого языка — CPython и BEAM. Они очень разные, поэтому отлично дополняют друг друга.

На картинке вы видите знак вопроса. Он связан с тем, что у нового языка пока нет окончательного названия. Есть только некоторые идеи — они связаны, простите, со свиньями. Также, в конце будет опрос — нужны ли минипиги в программировании. Ответьте, пожалуйста, это очень важно.

Скажу прямо — идея, главным образом, навеяна языком gleam. Это, на самом деле, просто феномен, а не язык. Причём, в полной мере я осознал этот факт уже после того, как написал о нём статью.

Один показательный факт — в gleam нет атомов. Атомы — это такие строки‑константы в эрланге, предназначенные для внутреннего использования. Причина, почему их нет — в том, что иногда можно обойтись без них, используя вместо этого фирменные gleam records. Кроме этого, автор считает чрезмерное использование атомов плохой практикой. Но, ввиду того, что атомы самым широким образом используются в эрланге, из‑за того, что их убрали, в значительной степени совместимость с эрлангом была нарушена.

Из‑за отсутствия атомов, в gleam крайне неудобно пользоваться OTP — центральной для эрланга библиотекой/платформой. Не так давно — то есть, когда уже прошла целая вечность времени — автор всё‑таки выпустил «дружественную к gleam» библиотеку для OTP, но она всё равно выглядит очень странно. Главный факт, который хочется отметить — всё это не имело под собой других оснований, кроме каприза автора.

В этом году gleam 10 лет — он появился позже языка zig. У него 22k звёзд на гитхабе, и несколько человек работают над ним full‑time. Неплохо, правда? Мне кажется, с таким подходом — это вообще оглушительный успех.

Отсутствие атомов — не единственное противоречие между языком gleam и эрлангом/BEAM. Например, компилятор gleam заставляет вас обработать все возможные случаи в конструкциях let и case — это напоминает парадигму из го для обработки ошибок. В то время, как в эрланге действует принцип «let it crash», что означает бросить исключение и позволить процессу умереть.

Лично мне совершенно не близок такой «бунт» gleam против своей целевой платформы, к тому же, добровольное нарушение совместимости выдаёт в авторе крайнюю наивность. Но есть один факт, который является однозначным достоинством gleam. Это — его минимализм. Где‑то я видел слайд, где на экран вывели все ключевые слова gleam крупным шрифтом, и потом сказали, что половина из них зарезервирована на всякий случай и сейчас не используется.

Минимализм — это действительно его фишка. Я как‑то подумал, что если из питона убрать классы, OOP, все явно мутирующие операции — получится всё равно более богатый по синтаксису язык, чем gleam. Это, кстати, и навело меня на соответствующие мысли.

Ещё есть проект hornbeam.dev, Он демонстрирует, что можно деплоить приложения на питоне, используя BEAM — и получить почти бесплатно кэширование и распределённость.

Ну и, наконец — где‑то в твиттере я прочитал: «I decided to build... (какую‑то вещь) because no one needs it». Мне это понравилось — сразу всем понятно, зачем.

Итак, давайте я вам покажу, как выглядит язык. Прежде всего, это форк CPython. Все конструкции питона работают (возможно, с небольшими изменениями), вся семантика остаётся той же. Области видимости переменных — такие же, как в питоне.

В питоне — мутабельный императивный рантайм, он останется таким же. Например, остаются, циклы for. Хотя на платформу BEAM циклы for тащить нет никакого смысла: в питоне есть list/dict comprehensions — это примерно то же самое, но подходит для функционального программирования гораздо лучше.

Но вот основные control structures я хочу сделать выражениями (expressions), как это принято в функциональных языках. Это операторы if, match и with:

exit_code =
  # хорошо, если бы здесь можно было начинать с новой строки
  if ready:
    run_command()
  else:
    abort()
    1

result =
  match val:
    case 0:
      "Success"
    case _:
      "Failure"

Отдельно скажу про оператор match: его я хочу сделать деструктивным. Это значит, что если ни один из вариантов не сматчился, должен случиться MatchError. Всё — согласно принципу «Let it crash».

Дальше возьмём операцию присваивания =. Её я хочу заменить на паттерн‑матчинг:

Point(x=x, y=y) = p

Синтаксис — точно такой же, как у case в операторе match, только нельзя использовать условия if. В результате, оператор = должен стать более функциональным во всех смыслах.

И последнее: ещё я бы улучшил работу с пробелами. Чтобы, например, такое парсилось нормально:

items =
    my_list
    .filter(None)

Это может быть особенно полезно, если if и match станут выражениями. Возможно, текущие ограничения в питоне, запрещающие переносить на новую строку, связаны с ограничениями предыдущего парсера.

Вот, пожалуй, и всё. Это — мой минимальный пакет изменений в питон, которые сделают его функциональным, почти ничего не ломая. Конечно, это не strict superset, потому что код, который раньше выполнялся без ошибок, теперь может бросить ошибку — из‑за того же деструктивного match. Но всё равно — это почти тот же питон.

Кроме минимального пакета изменений, у меня ещё есть опциональный пакет. В духе минимализма из gleam, его, конечно следует отложить. Но всё равно, не могу не поделиться своим синтаксисом.

Вопрос первый: какой может быть функциональный язык без пайплайн‑оператора? Хотя, например, в эрланге его нет, и никто не говорит, что эрланг не функциональный. Тем не менее: пайплайн‑оператор мне представляется в виде двоеточия:

def is_even():
  return x % 2 == 0

[1, 2, 3, 4, 5]
..filter(is_even)
..print()

Также, мне пришла в голову конструкция match def, которая делает паттерн‑матчинг нескольких функций с одинаковым названием. Это «склеенные» def и match. Приведу пример с обложки — это сортировка пузырьком в функциональном стиле:

match def bubble_sort(lst: list[int], acc: list[int], was_swapped: bool):
    case [] = lst:
        (acc[::-1], was_swapped)
    
    case [x] = lst:
        ([x, *acc][::-1], was_swapped)
    
    case [x, y, *rest] = lst if x > y:
        bubble_sort([x, *rest], [y, *acc], True)
    
    case [x, y, *rest] = lst:
        bubble_sort([y, *rest], [x, *acc], was_swapped)

Но это я просто хотел похвастаться оригинальным синтаксисом. В минимальном варианте, новый язык — это всего лишь плюс‑минус обычный питон.

Отдельный вопрос — как это всё будет компилироваться для BEAM. У этого рантайма есть свои особенности, главная из которых — неизменяемые структуры данных. То есть, даже такая конструкция вызывает вопросы:

x += 1

В gleam эту проблему решают так, что у переменной x может быть несколько версий: x@1, x@2 и так далее.

Как я уже говорил, циклы for выбрасываем: вместо них есть list/dict comprehensions. Для словарей есть чудесный оператор‑палка:

my_dict |= {'key': value}

Мутирующие операции вроде my_dict['key'] = value не нужны, их тоже выбрасываем. Также, в новом эрланге есть named records — для них оператор‑палка тоже пригодится.

Для работы со списками нужный синтаксис в питоне тоже есть:

[head, *new_list] = list

Код из репозитория gleam вполне подойдёт для компиляции кода для BEAM. Хотя парситься он может моим форком CPython. Но это тоже детали.

Наконец, мы подошли к самому интересному вопросу — это, конечно, вопрос брендинга. Хотя новый язык очень похож на питон — всё‑таки, он отличается. Да и прямой совместимости нет, поэтому файлы вряд ли должны иметь расширение *.py. Другими словами, языку нужно имя, а проекту — лицо (или хотя бы пятачок).

То, что розовый цвет приносит успех — это уже проверено на примере gleam. И я подумал, что можно разыграть счастливую свинскую карту и поместить на логотип розового поросёнка. Но вопрос о названии оставался открытым: piglang — это как‑то слишком толсто. Всё‑таки, нужен именно поросёнок, а не взрослая свинья.

Тут я вспомнил, что свиньи с давних пор были персонажами английских сказок и подумал, что, вероятно, в английском языке есть достаточно много слов для передачи звуков, которые издают свиньи. Так и оказалось: «oink» — это общее хрюканье, «grunt» — “ворчание” взрослого кабана, и «squeal» — визжание поросёнка. Немного примерив последнее слово, я решил, что оно может подойти.

squea‑lang, как вам такой вариант? Файлы исходного кода могут иметь расширение .ea, на логотипе — розовый поросёнок. В конце концов, минипиги крайне фотогеничные. А вы что думаете?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Нужны ли в программировании минипиги?
100%Нужны!5
0%Нет!0
Проголосовали 5 пользователей. Воздержались 2 пользователя.