
У меня двадцать лет в IT. Большую часть этого времени я проектировал и эксплуатировал инфраструктуру на PostgreSQL. Сейчас работаю архитектором: Go, Python, Postgres, Redis, ClickHouse, мониторинг на десятки тысяч баз. До этого писал на Ruby, пробовал Rust. Классический бэкенд-инженер со всеми вытекающими привычками: императивный код, мутабельное состояние, постоянные if err != nil { return err }.
А потом я начал писать бэкенд на Gleam — молодом функциональном языке на BEAM (Erlang VM), который появился в стабильной версии только в 2024 году. Навык ещё в разработке, но бэкенд уже работает, и я не жалею. Путь был... познавательным.
Эта статья — не туториал и не рекламный буклет. Это честный рассказ о том, почему я выбрал Gleam, какие шишки набил, что мне понравилось настолько, что я не хочу возвращаться, и что до сих пор бесит.
Что я делаю?
Разрабатываю голосовую игру для Яндекс Алисы. Ребёнок управляет кафе: принимает заказы, готовит блюда, обслуживает посетителей. Звучит просто, но под капотом:
HTTP-сервер, обрабатывающий запросы от платформы Алисы (JSON-протокол со своей спецификой)
Конечный автомат (FSM) с десятками состояний и переходов между сценами
Хранение состояния сессий в Redis (Алиса — stateless, состояние нужно передавать или хранить самому)
HMAC-SHA256 подпись состояния для защиты от подделки
Админ-панель на React для управления диалоговыми сценариями через API
Озвучка через ElevenLabs, звуковые эффекты, SSML-разметка
Стек: Gleam + Wisp (HTTP) + Mist (сервер) + Valkyrie (Redis) + Nginx + systemd + Ubuntu. Деплой — обычный Linux-сервер, без Docker и Kubernetes.
Почему Gleam, а не [ваш любимый язык]
Почему не Go
Go — основной язык в моём стеке, на нём написаны системы, которые я проектирую и поддерживаю. Для инфраструктурных сервисов он прекрасен: быстрая компиляция, горутины, один бинарник. Но для моделирования предметной области Go — страдание.
В Go нет алгебраических типов данных. Нет pattern matching. Обработка ошибок — бесконечные if err != nil. Когда ты моделируешь конечный автомат с двадцатью состояниями, где каждый переход должен быть валидным, Go превращается в минное поле: ты постоянно боишься забыть проверку, пропустить кейс, оставить невалидное состояние.
Почему не Rust
Rust я изучал перед Gleam и даже написал на нём прототип. Rust великолепен для системного программирования, но для HTTP-бэкенда с Redis — избыточен. Borrow checker решает проблемы, которых у меня нет: я не управляю памятью вручную, не пишу драйверы. А вот когнитивная нагрузка от сложности языка — это цена, которую я плачу за ненужные мне гарантии.
Почему не Elixir
Elixir — ближайший родственник Gleam, тоже на BEAM. Отличный язык. Но: динамическая типизация. Для небольшого-проекта, где я не могу позволить себе роскошь тестового отдела и CI с тысячей тестов, статические типы — это мой страховой полис. Gleam ловит целые классы ошибок на этапе компиляции, которые в Elixir всплывают только в runtime.
Почему Gleam
Gleam попал в пересечение всех моих требований:
Статическая типизация с алгебраическими типами и pattern matching — для моделирования FSM(конечного автомата).
BEAM под капотом — конкурентность, отказоустойчивость, горячая перезагрузка (теоретически).
Простой синтаксис — после Rust - это как задержать дыхание на пару минут и потом выдохнуть. Все предельно просто, никаких макросов, минимум магии.
Result-типы вместо исключений — каждая ошибка явная, каждый путь обработан.
JavaScript-интероп — для тех случаев, когда нужной библиотеки на Gleam нет (а таких случаев много).
Конечный автомат на типах - главная победа
Конечный автомат — сердце голосового навыка. У игры есть сцены (главное меню, кухня, зал, мини-игра), и в каждой сцене — свои допустимые переходы. Игрок не может «готовить», находясь в главном меню, и не может «принять заказ» на кухне.
В Go или Python это обычно делается через строки или enum-ы с runtime-проверками:
// Go — runtime error, если забыл проверку if state == "kitchen" && action == "take_order" { return errors.New("invalid action for kitchen") }
В Gleam это моделируется на уровне типов:
// Gleam — невалидный переход не компилируется pub type Scene { MainMenu Kitchen(KitchenState) Hall(HallState) MiniGame(MiniGameType) } pub type KitchenState { Idle Cooking(dish: Dish, time_left: Int) Done(dish: Dish) } pub fn handle_kitchen(state: KitchenState, input: UserInput) -> Result(Scene, UserError) { case state, input { Idle, Cook(dish) -> Ok(Kitchen(Cooking(dish, dish.cook_time))) Cooking(_, ), _ -> Error(StillCooking) Done(dish), Serve -> Ok(Hall(Serving(dish))) _,_ -> Error(InvalidAction) } }
Красота в том, что компилятор заставляет меня обработать все комбинации состояний и действий. Если я добавлю новую сцену и забуду написать обработчик — код не скомпилируется. В Go или Python это была бы ошибка, которая проявилась бы только, когда реальный пользователь попал бы в необработанную ветку.
Typed Errors: почему UserError лучше, чем panic
В начале проекта я обрабатывал ошибки как в Go — возвращал строки. Потом рефакторнул на типизированные ошибки, и это изменило всё.
pub type UserError { SessionExpired InvalidState(details: String) RedisConnectionFailed(reason: String) SceneNotFound(scene_id: String) HmacVerificationFailed }
Теперь каждая функция явно декларирует, что может пойти не так:
pub fn load_session(session_id: String) -> Result(Session, UserError) { use raw <- result.try( redis.get(session_id) |> result.map_error(fn(e) { RedisConnectionFailed(e.message) }) ) use session <- result.try( decode_session(raw) |> result.map_error(fn(_) { InvalidState("corrupted session data") }) ) verify_hmac(session) |> result.map_error(fn(_) { HmacVerificationFailed }) }
Оператор use в Gleam — это то, что делает цепочки Result-ов читаемыми. Без него код был бы лестницей из case ... { Ok() -> ... Error() -> ... }. С ним — линейный поток, где каждый шаг может упасть, и ты точно знаешь, как именно.
Экосистема: где больно
Не буду врать: экосистема Gleam — это одновременно и самая сильная проблема, и причина, по которой ты можешь стать контрибьютором чего-то важного.
Redis: путь от radish к valkyrie
Первый клиент Redis, который я попробовал — radish. Работал, но с ограничениями. Потом перешёл на valkyrie — более зрелый, лучше API. Но даже valkyrie не покрывает все команды Redis. Несколько раз пришлось лезть в исходники и дописывать.
Для сравнения: в Go я бы взял go-redis и не думал. В Gleam выбор Redis-клиента — это исследовательский проект на пару вечеров.
HTTP: Wisp и его особенности
Wisp — HTTP-фреймворк для Gleam. Работает поверх Mist (HTTP-сервер на BEAM). В целом — приятный, минималистичный. Но есть неочевидный момент: Wisp использует String-based API, а не StringTree (StringBuilder). Я потратил час на отладку, потому что пытался передать StringTree туда, где ожидался String. Компилятор подсказал, но не сразу было ясно, почему типы не совпадают.
Библиотеки: чего не хватает
На момент написания статьи мне не хватало:
Полноценного HMAC-SHA256 (пришлось делать через Erlang FFI).
Продвинутой работы с JSON (gleam_json базовый, для сложных вложенных структур неудобен).
Хорошего логгера с уровнями и структурированным выводом.
ORM или хотя бы query builder.
Это цена раннего использования нового языка. Но это и возможность: каждая библиотека, которую ты напишешь, получает очень высокий шанс стать БИБЛИОТЕКОЙ в экосистеме.
Что мне понравилось настолько, что я не хочу возвращаться к другим языкам
Exhaustive pattern matching
Когда я добавляю новый вариант в тип — например, новую сцену в игре — компилятор показывает все места, где я забыл его обработать. Не один, не два — все. В Go я бы узнал об этом от пользователя в production.
Pipe-оператор
Оператор |> в Gleam делает код читаемым слева направо, а не изнутри наружу:
// Вместо этого: json.to_string(response.build(handle_input(parse_request(raw_body)))) // Пишешь это: raw_body |> parse_request |> handle_input |> response.build |> json.to_string
После pipe-оператора возвращаться к вложенным вызовам физически неприятно.
Иммутабельность по умолчанию
Всё иммутабельно. Нет переменных, которые кто-то может изменить из другого потока. Нет race conditions на уровне данных. Для бэкенда, обрабатывающего конкурентные запросы — это не просто удобство, это архитектурная гарантия.
Сообщения об ошибках компилятора
Gleam унаследовал от Elm-традиции человечные сообщения об ошибках. Когда типы не совпадают, компилятор не просто говорит «type mismatch» — он объясняет, что ожидалось, что получено, и часто подсказывает, как исправить. После gcc и даже rustc — это глоток свежего воздуха.
Что бесит
Нет мутабельных переменных совсем. Иногда хочется просто инкрементировать счётчик. Мне сложно игнорировать свои 20 лет программирования с мутабельными переменными. В Gleam для этого нужен рекурсивный вызов или fold. Идеологически чисто, практически — иногда утомляет.
Нет раннего return. В Go я пишу guard clause — проверил условие, вернулся. В Gleam каждый путь должен быть частью выражения. Для сложных валидаций это удлиняет код.
Маленькое сообщество. Если ты застрял — Stack Overflow не поможет. Discord Gleam — основной канал поддержки, и он отзывчивый, но это не масштаб Go или Python.
Отсутствие IDE-поддержки уровня GoLand/IntelliJ. Gleam LSP работает, но рефакторинг, навигация, автодополнение — всё на уровне «достаточно, но не более».
Документация библиотек. Hexdocs есть, но многие пакеты документированы по принципу «типы говорят сами за себя». Иногда говорят. Иногда — молчат.
Деплой: скучно и надежно
У меня простой проект. Поэтому: никакого Docker, никакого Kubernetes.
Вот весь деплой:
gleam export erlang-shipment — собирает релиз
scp на сервер
systemd unit для запуска и рестарта
Nginx как reverse proxy с SSL
BEAM-релиз — это самодостаточная директория с Erlang runtime и скомпилированным кодом. Работает как обычный процесс. Потребление памяти — около 30–50 МБ. Для side-проекта на VPS за 500 рублей в месяц — более чем достаточно.
Стоило ли оно того?
Да. Но с оговорками.
Стоило, потому что: я перестроил своё мышление. После двадцати лет императивного кода я теперь думаю типами и паттернами, а не циклами и мутациями. Это сделало меня лучшим инженером даже в Go — я стал чаще использовать интерфейсы как discriminated unions, строже обрабатывать ошибки, избегать мутабельного состояния.
Стоило, потому что: Gleam заставляет проектировать перед кодированием. Когда у тебя нет null, нет исключений, нет мута>ций — ты вынужден продумать все пути данных заранее. Это медленнее на старте и быстрее на дистанции.
С оговоркой: для production-системы с SLA и on-call я бы пока выбрал Go или Elixir. Экосистема Gleam не готова для «взрослого» production, где нужны десятки интеграций из коробки. Но для side-проекта, pet-проекта, микросервиса с узким скоупом — Gleam идеален.
Кому стоит попробовать Gleam
Go/Java/C#-разработчикам, которые хотят попробовать функциональное программирование без боли Haskell. Gleam — самый мягкий вход в мир типизированного функционального программирования.
Elixir-разработчикам, которым не хватает статических типов. Gleam компилируется в Erlang и может использовать любые Erlang/Elixir-библиотеки.
Тем, кто пишет конечные автоматы, парсеры, обработчики протоколов — задачи, где важна корректность и полнота обработки всех случаев.
Тем, кто устал от if err != nil и хочет попробовать мир, где обработка ошибок — не ритуал, а часть дизайна.
Вместо заключения
Gleam — не серебряная пуля. Это молодой язык с маленькой экосистемой и амбициозными идеями. Но он решает реальную проблему: даёт статическую типизацию и функциональную чистоту без порога входа Haskell и без когнитивной нагрузки Rust.
Если вы двадцать лет писали императивный код и чувствуете, что стагнируете — попробуйте написать что-нибудь на Gleam. Необязательно целый бэкенд. Начните с Exercism, потом — CLI-утилита, потом — маленький API. Ваш мозг скажет спасибо.
А если напишете библиотеку — вы автоматически станете одним из ведущих контрибьюторов экосистемы. Нас пока мало. Заходите.
P.S. Если интересно, в следующей статье покажу подробнее архитектуру конечного автомата на типах Gleam — как моделировать диалоговые сценарии так, чтобы невалидные переходы были невозможны на уровне компиляции.
Комментарии (33)

napolskih
20.03.2026 17:06Спасибо за контент по BEAM, Erlang и Elixir.
Тоже имею 20+ лет опыта разработки и пару лет назад погрузился в Elixir. Давно меня так ничего не впечатляло. Удалось получить работу, удалось написать несколько фичей на нем в прод, но пришлось вернуться к Ruby и менеджменту. Надеюсь еще написать что-то на Elixir, а позже может быть и на Gleam.

AlexeiZhuravlev Автор
20.03.2026 17:06Спасибо! Очень знакомая история — после 20 лет в IT думаешь, что тебя уже сложно чем-то удивить. А потом пробуешь ФП на BEAM — и вдруг снова чувствуешь себя джуном, который открывает что-то по-настоящему новое. Давно забытое ощущение.
Интересно, что вы пришли через Elixir. Я сознательно выбрал Gleam именно из-за статических типов — после Go хотелось строгости, но без когнитивной нагрузки Rust. А что в Elixir впечатлило больше всего — BEAM как платформа или сам язык?

napolskih
20.03.2026 17:06Конечно и BEAM как платформа, а так же концепции заложенные в язык и тулинг. Иммутабельность, паттерн-матчинг, пайп-оператов, with, док-тесты, качество документации. Многое, всего уже не помню тк пришлось отойти от темы (сбили на взлете, сокращения).

AlexeiZhuravlev Автор
20.03.2026 17:06Да, пайп-оператор и иммутабельность — это то, что меняет голову навсегда. Я теперь даже в Go-коде ловлю себя на том, что думаю пайпами.
Сочувствую насчёт сокращений. Но BEAM-мышление не теряется — когда будет возможность вернуться, порог входа будет совсем другой.

StanEgo
20.03.2026 17:06Зачем он C#-разработчикам, у которых есть F#? С exhaustive pattern matching, pipe-operator, мутабельными переменными и computational expression, на которых красиво делаются и state machines, и ранний return. Всё это в итоге можно собрать в один бинарник как в Go.

AlexeiZhuravlev Автор
20.03.2026 17:06F# — отличный язык, и для C#-разработчиков это действительно более естественный шаг в ФП — остаёшься на .NET, вся огромная и зрелая экосистема под рукой. Спорить с этим было бы странно.
Разница — в рантайме. F# работает на CLR, Gleam — на BEAM. Это разные модели конкурентности: лёгкие процессы с изоляцией ошибок, supervision trees, hot code reload. Для голосовых навыков, чатов, real-time систем это имеет значение. Для типичного бэкенда — нет, и F# будет практичнее.
А насчёт мутабельных переменных — я в статье честно написал, что их отсутствие в Gleam иногда бесит. F# тут прагматичнее.

remindscope
20.03.2026 17:06В современных версиях Java есть все те же удобства, куча зрелых библиотек, а пайпы можно писать через optional или stream.
Может я чего-то недопонял из материала, но для меня как джависта серьезных причин присмотреться к этому языку не нашлось.

AlexeiZhuravlev Автор
20.03.2026 17:06Справедливо. Если Java закрывает ваши задачи и экосистема устраивает — нет смысла менять ради синтаксического сахара.
Разница глубже, чем пайпы. Optional и Stream — это ФП-элементы поверх императивного языка. В Gleam иммутабельность и exhaustive pattern matching — не опция, а единственный способ писать код. Нет null, нет исключений, нет мутабельного состояния. Компилятор не даёт забыть ветку в case — вообще, ни одну. В Java sealed classes + switch expressions приближаются к этому, но не заставляют.

DOKL57
20.03.2026 17:06Тут мог бы подойти котлин, если хочется уйти от многословности java. Получить null-safety на уровне типов и exhaustive pattern matching через when+sealed (компилятор тоже не даст забыть ветку). Плюс он поощряет иммутабельность и функциональщину. Но несмотря на это, всё же является мультипарадигменным ЯП. Ещё очевидный плюс - большая экосистема вокруг языка. Но не факт, что она тут пригодится.
Если цель - писать чистый ФП-код и уйти от минусов jvm к минусам beam, то gleam действительно кажется хорошим вариантом, если исходить из статьи (не писал на нём).
А в elixir, кстати, скоро появится gradual typing, сейчас он уже есть в RC-ветке.
napolskih
20.03.2026 17:06В BEAM большая ценность это сама платформа. Акторная модель, возможность запустить, к примеру, 300к параллельных процессов и сохранять отзывчивость. Построение кластерных приложений. Я не вижу конкурентов. За развитием Elixir слежу.

t1nker
20.03.2026 17:06NullPointerException пугает даже меня - не джависта. Одна из причин присмотреться к другим языкам

9lLLLepuLLa
20.03.2026 17:06Можете развернуть мысль, в чем, как вы считаете, боль хаскеля ?

AlexeiZhuravlev Автор
20.03.2026 17:06Говорю как человек с двадцатью годами императивного кода, не как эксперт по Haskell. Моя «боль» — это боль порога входа. Чтобы написать HTTP-сервер на Gleam, мне хватило выходных. Чтобы сделать то же на Haskell, мне сначала нужно понять, почему IO — это монада и зачем мне это знать.
Порог входа — не в синтаксисе, а в количестве концепций, которые нужно усвоить до того, как начнёшь писать что-то полезное. Монады, функторы, классы типов, ленивые вычисления по умолчанию, IO как монада. Каждая по отдельности понятна, но все вместе — это серьёзная нагрузка на мозг.Уверен, что для тех, кто уже в Haskell, это не боль, а сила. Но я писал статью для таких же как я — Go/Java/C#-разработчиков, которые хотят попробовать ФП без огромных временных затрат.

9lLLLepuLLa
20.03.2026 17:06Спасибо. А вот скажите как обстоят дела с логированием тут ? Можно встроить это в pipe ? И как вообще работать с IO ?

AlexeiZhuravlev Автор
20.03.2026 17:06Логирование в Gleam можно условно разделить так:
Дебаг. Встроенное ключевое слово
echo— вставляешь в любое место пайпа, оно пропускает значение через себя и печатает в stderr с указанием файла и строки:[1, 2, 3] |> list.map(fn(x) { x + 1 }) |> echo |> list.map(fn(x) { x * 2 })Билд-тул предупредит, если забудете убрать перед публикацией. Есть ещё
io.debug— делает то же самое, но без метаданных.Боевое логирование. Пакет
logging— обёртка над Erlang logger. Уровни, форматирование, всё стандартно. Естьglimt— более продвинутый, со структурированным JSON-выводом и контекстами.

Filipp42
20.03.2026 17:06Мне вот интересен Lean 4. Это одновременно и язык программирования, и помощник для доказательств. Он помогает изучать математику. Если ты доказал теорему, и верифицировал доказательство в Lean, можно быть практически уверенным, что доказательство правильное.

AlexeiZhuravlev Автор
20.03.2026 17:06Интересная ниша — язык как инструмент доказательства, а не только разработки. С Lean не работал. Ждем от вас статью про него))

nice_nick_matter
20.03.2026 17:06IO является монадой потому, что ввод/вывод в haskell сделали на монадах. Почему нужно знать, что IO монада? Потому, что нужно уметь работать со значениями "упакованными" в монаду IO, а это умеет делать оператор bind -- >>= (еще это умеют делать unsafePerformIO и друзья, но unsafe в названии у них не просто так! И со значениями в монаде IO надо работать именно с помощью bind). Все просто!

AlexeiZhuravlev Автор
20.03.2026 17:06Спасибо за объяснение! Вы как раз подтверждаете мою мысль — для вас это «всё просто», и я верю. Но в вашем объяснении уже есть «монада», «bind», «>>=», «unsafePerformIO» и «упаковка значений». Для обычного разработчика, который хочет напечатать строку в консоль, это пять новых концепций до первого результата. В Gleam это
io.println("hello")— и готово.

evgeniy_kudinov
20.03.2026 17:06Спасибо за краткое знакомство с Gleam. Буду рад дополнительным материалам по нему.

ImagineTables
20.03.2026 17:06Оператор |> в Gleam делает код читаемым слева направо, а не изнутри наружу
Крутецки выглядит. А можно передать собранную пайпу как лямбду аргументом куда-нибудь?

AlexeiZhuravlev Автор
20.03.2026 17:06Сам пайп
|>— это синтаксический сахар, а не значение, его нельзя передать куда-то как аргумент. Но можно собрать цепочку в анонимную функцию и передать её:let transform = fn(x) { x |> string.trim |> string.uppercase |> string.append("!") } list.map(items, transform)
ImagineTables
20.03.2026 17:06Я перестал понимать. Это во что развернётся?
Если…
raw_body |> parse_request |> handle_input |> response.build |> json.to_string…разворачивается в
json.to_string(response.build(handle_input(parse_request(raw_body)))), то…x |> string.trim |> string.uppercase |> string.append("!")…должно развернуться в
string.append(string.uppercase(string.trim(x)), "!")?Если да, то как-то упячно выглядит. По сравнению с традиционным:
x .trim() .uppercase() .append("!")Я изначально подумал, что
|>удобен, чтобы собирать конвейер из разных частей. Например,handle_input,response.buildиjson.to_string. А для набора операций обычной иммутабельной строки зачем? Где неявно передаётсяthis?А вообще, меня эта тема зацепила тем, что я давно думаю, как сделать идеальные чейнинги (на JS или других, более функциональных, языках), где одним выражением можно результат первого
filterразбить на два другихfilter, и с каждым сделать что-то своё, без промежуточных переменных. Когда говорят, что «jQuery устарел», в этом отношении это правда — он так не умеет )) А хотелось бы.
AlexeiZhuravlev Автор
20.03.2026 17:06Да, разворачивается именно так. И вы правы — для строки
x.trim().uppercase().append("!")читается лучше. Но в этом и суть: method chaining работает, пока все методы принадлежат одному объекту. Как только нужно протащить данные через функции из разных модулей —parse_request, потомhandle_input, потомresponse.build— методы кончаются, а пайп продолжает работать.В Gleam нет методов и нет
this— функции принадлежат модулям, а не данным. Поэтомуstring.trim(x)вместоx.trim(). Пайп компенсирует отсутствие методов — и делает это универсально, потому что работает с любой функцией, а не только с методами одного типа.Кстати, ваша идея про разветвление после filter — это по сути то, что в ФП делается через
let. Не промежуточные переменные в императивном смысле, а именованные привязки:let filtered = items |> list.filter(is_active) let group_a = filtered |> list.filter(is_premium) let group_b = filtered |> list.filter(fn(x) { !is_premium(x) })Пайп не пытается заменить всё — он для линейных цепочек. Когда поток разветвляется — let и отдельные пайпы.

ImagineTables
20.03.2026 17:06Ясно, спасибо.
Кстати, ваша идея про разветвление после filter — это по сути то, что в ФП делается через let. Не промежуточные переменные в императивном смысле, а именованные привязки
Это меня как раз и не устраивает. У вас в примере
group_a = filtered |> list.filter(is_premium). Я полагаю, это только для примера, в жизни, понятное дело, напишут неgroup_a, аpremium_group, и нарушится DRY:is_premiumУЖЕ описывает ситуацию. Если всерьёз рассмотреть использование имён типаa, это не способ избежать нарушений DRY, это способ замаскировать нарушение. Единственный способ избежать нарушений DRY — вообще избегать всего поименованнного, поэтому я и думаю, как такие вещи писать одним выражением. Хотя бы запись чтоб была исключающая противоречия, уж потом можно подумать про атомарность транзакции и т.п.
AlexeiZhuravlev Автор
20.03.2026 17:06Да для примера. Но мне кажется, тут не нарушение DRY, а два разных уровня абстракции.
is_premium— это предикат.premium_group— это результат применения предиката к конкретному набору. Они не дублируют друг друга — они на разных этажах.

blackyblack
20.03.2026 17:06Rust при прочих равных лучше подходит, я считаю. Все перечисленное он лучше умеет. При необходимости можно переключаться на императивный стиль. Экосистема лучше. ИИ агенты с растом дружат лучше, чем с экзотикой. Когнитивная нагрузка выше, если надо работать с чужим кодом. Если код контролировать, то все ок.
Удивлен, что при таком богатом опыте с другими языками, вы еще пишете на Go. Я от него испытал отвращение - все сделано максимально криво и првоцирует писать плохой код.

AlexeiZhuravlev Автор
20.03.2026 17:06Про Rust — согласен, что он мощнее как язык. Но для моей задачи (голосовой навык, FSM, Redis, конкурентные сессии) его сила избыточна, а BEAM под капотом Gleam даёт модель конкурентности, которой в Rust нет из коробки — лёгкие процессы, изоляция ошибок, supervision trees. Это не про синтаксис, а про рантайм.
Про Go — я в основном занимаюсь архитектурой, кода пишу мало. Go в нашем стеке — не мой личный выбор, а стандарт, который выбирает компания. И его выбирают именно за то, за что вы его критикуете — он простой, предсказуемый, любой новый разработчик входит в проект за короткий срок. Для команд в 10-50 человек это перевешивает элегантность. Отвращение к Go я понимаю, сам в статье написал про бесконечные «if err != nil» — но архитектурные решения принимаются не по ощущениям одного человека, а по стоимости поддержки для всей команды.

fenom82
20.03.2026 17:06Как будто бы Scala хорошо подошла. Не рассматривали её в качестве альтернативы?
Более зрелые тулы, функциональный подход, грин треды, авторы где если хотите

AlexeiZhuravlev Автор
20.03.2026 17:06Scala не рассматривал, честно. Она мощная, но для side-проекта мне был важен минимальный порог входа. Gleam можно выучить за выходные — у Scala порог существенно выше, особенно если до этого не был в JVM-мире.
Surrogate
Я думал GLEAM - это другое)
Специфический профсоюз внутри M$FT
AlexeiZhuravlev Автор
Представляю, что выдаёт гугл тем, кто впервые пытается загуглить этот язык. Зато запоминается!