Formatting code should be unnecessary 🔥 Горячее 💬 Длинная дискуссия
Форматирование кода должно быть лишним
В 80-х это уже знали.
Мой школьный учитель информатики, мистер Пейдж, участвовал в разработке компилятора Ada. Когда я в 2016-м жаловался на линтеры, он напомнил: проблему решили 40 лет назад. В Ada исходники не хранили — использовали IR-дерево DIANA. Каждый смотрел его в своём стиле: отступы, пробелы — всё равно.
Сейчас, в 2025-м, мы всё ещё спорим о запятых.
Как это работало
Рабочая станция Rational R1000 (1985) хранила не текст, а DIANA. IDE позволял редактировать дерево напрямую — проекционное редактирование. Компиляция была инкрементной, рефакторинг мгновенным, а «исходник» — просто красивой печатью дерева.
Плюсы: никаких holy-war’ов о табах, быстрая интеграция, встроенный VCS и отладка.
Минус: требовалась железная станция и знание Ada.
Вывод
Не нужно возвращаться к проекционным редакторам, но можно ли встроить идею «храним структуру, а не текст» в современные языки и IDE? Тогда форматирование станет личным вкусом, а не командным законом.
Комментарии (422)
- Одни считают форматирование важным каналом коммуникации и показателем вкуса/опыта разработчика, другие — пустым байкшедом, который должен решаться автоматическим линтером без обсуждений.
- Хранение кода не как текста, а как IR/AST (пример — Ada/DIANA, Unison) позволяет каждому видеть свой вариант форматирования, но ломает привычные grep, diff, git и другие текстовые инструменты.
- Проекционное редактирование (JetBrains MPS, Chrome DevTools «pretty») демонстрирует «один IR — много представлений», но требует специальных IDE и пока не стало массовым.
- Проблема смешанных языков, legacy, необходимости универсального стандарта IR и инерции экосистемы тормозит переход от plain-text.
- Автоформатеры (gofmt, Prettier, Black) уже закрывают 90 % вопросов: на сохранении/коммите единый стиль, локально можно настроить git-фильтры smudge/clean.
Algebraic Effects in Practice with Flix
Алгебраические эффекты на практике в Flix
Алгебраические эффекты — уже не академия. Это рабочий инструмент, который сегодня делает код:
- Тестируемым — «что» отделено от «как»; mock-и и DI не нужны.
- Прозрачным — сигнатура функции сразу показывает все побочные действия (IO, сеть, исключения).
- Гибким — async/await, корутины, backtracking реализуются обычными библиотеками, без изменения языка.
В отличие от монад, эффекты понятны без теории категорий и работают «из коробки» в языке Flix.
Мотивирующий пример
Без эффектов:
def calculateSalary(base, percent) -> float:
# может отправить письмо бабушке
С эффектами (Flix):
def calculateSalary(base: Float64, percent: Float64): Float64 \ {Email} =
...
Сигнатура не лжёт: любой вызов Email
будет отслежен компилятором.
Обработчики эффектов (интуиция)
Эффект = операция + обработчик.
Код бросает операцию, обработчик решает, что с ней делать.
eff Ask { // объявляем эффект
pub def ask(): String
}
def greet(): String \ Ask = // используем
"Hello " + Ask.ask()
def main(): Unit = // обрабатываем
println(greet() with Ask {
def ask() = "World"
})
Реальный проект: рекомендательная система фильмов
Задача: достать данные из SQLite, вызвать внешний AI-сервис, кешировать результат, логировать.
Эффекты: Db
, Http
, Log
, Cache
.
def recommend(user: String): List[Movie] \ {Db, Http, Log, Cache} =
Cache.getOrElse(user,
for {
prefs <- Db.query(user)
_ <- Log.info("Prefs loaded")
recs <- Http.post("ai.example.com", prefs)
_ <- Log.info("AI answered")
_ <- Cache.put(user, recs)
} yield recs)
Тест: подменяем обработчики на in-memory реализации — никаких реальных запросов.
Куда дальше
- Попробовать онлайн: https://play.flix.dev
- Документация: https://doc.flix.dev
- Репозиторий: https://github.com/flix/flix
Flix ещё молод, но уже поддерживает эффекты, регионы, структурную конкурентность и Datalog.
Комментарии (42)
- Участники восторгаются идеей алгебраических эффектов: они проще монад, решают «цветную» проблему функций и позволяют гибко компоновать побочные эффекты.
- Примеры уже есть: экспериментальная реализация в OCaml 5, библиотеки Effect и Effectively для TypeScript, языки Koka, Effekt, Unison.
- Отличие от ОО-интерфейсов: эффекты явно указывают контекстные требования (Net, IO) и позволяют подменять реализацию динамически, а не статически.
- Критика: система всё равно «окрашивает» код, требует прокидывать эффекты через весь стек вызовов и пока выглядит академично/громоздко.
- Практические вопросы: как скрыть «дебажный» вывод, не нарушая типов, и можно ли обойтись без переписывания сигнатур каждой промежуточной функции.