flang — язык с доказуемым завершением Чего в языке пока нет: проверенный список
0%

Чего в языке пока нет: проверенный список

Чего в языке пока нет: проверенный список

Язык ставится одной командой: brew install digitable-lol/tap/flang. Номера версий в разборе ниже — те, что стояли на момент его написания.

В репозитории есть редкая вещь: язык ведёт список собственных недостач. Файл flang/examples/leetcode/index.json содержит раздел «чего не хватает языку» — список того, что язык не умеет, с объяснением каждого пункта, и раздел «невыразимые» — двенадцать задач LeetCode, которые на flang не пишутся, с указанием причины.

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

Утверждение о недостаче — единственное, которое не ломается, когда становится ложным

Это самое ценное, что случилось с языком за прошедшие сутки, и это не про flang, а про любой проект, который ведёт документацию.

В прошлой редакции этой главы мы писали: «список местами отстаёт от кода на несколько часов». Формулировка была слишком мягкой. Шестого августа автор языка проверил каждую запись запуском, и оказалось, что восемь записей из пятнадцати — неправда. (Мы читали список чуть раньше, когда в нём было шестнадцать записей; на счёт неправды это не влияет.) Не устарели на час: просто неправда. Модульность работала, структурное сравнение в примерах работало, сравнение строк давно свели между слоями, встроенные формы «символ» и «пусто» работали, списочная форма «соединить» работала, вызов функции без аргументов работал, псевдоним типа работал.

Причина названа в репозитории точнее, чем сумели мы, и её стоит привести дословно из шапки flang/test/missing.test.mjs:

Заметить это было нечем: недостача — единственное утверждение о языке, которое НЕ ЛОМАЕТСЯ, когда становится ложным. Тест, проверяющий, что чего-то нет, никто не пишет; тест, проверяющий, что что-то есть, на такую запись не посмотрит.

Вдумайтесь в асимметрию. Утверждение «язык умеет X» защищено самим собой: оно живёт в тесте, и если X сломается, тест покраснеет. Утверждение «язык не умеет X» не защищено ничем. Оно тихо становится ложным ровно в тот момент, когда кто-то делает работу, — то есть при успехе, а не при поломке. Чем лучше идёт проект, тем быстрее гниёт его список ограничений.

А цена высокая: по такому списку и судят, чему верить. Формулировка в том же файле: «Список наполовину из выдуманного хуже отсутствующего: он и есть то самое „проверено на словах“, против чего написан весь проект».

Что с этим сделали: программа-улика на каждую недостачу

Решение оказалось единственным работающим. У каждой оставшейся недостачи в flang/test/missing.test.mjs стоит программа, которая её показывает, и тест требует, чтобы программа по-прежнему не работала.

const УЛИКИ = [
  {
    чего: "логические операции",
    показ: () => { /* ни «и», ни «или», ни «не» для признаков */  },
  },
  
]

test("каждая недостача из каталога подтверждается программой", () => {
  for (const улика of УЛИКИ) {
    assert.ok(улика.показ(),
      `недостача «${улика.чего}» БОЛЬШЕ НЕ СУЩЕСТВУЕТ: программа-улика работает. ` +
      `Уберите запись из «чего не хватает языку» в flang/examples/leetcode/index.json`)
  }
})

Направление проверки перевёрнуто: починили недостачу — тест краснеет, и краснеет с готовой инструкцией, что править. Плюс второй тест, страхующий от обратной беды: у каждой записи каталога обязана быть улика, иначе она снова станет непроверяемой. Исключение одно и названо по имени — запись «проверка самого этого списка», которая про сам список и улики иметь не может.

Приём стоит запомнить отдельно от flang. Если ваша документация где-то говорит «мы этого не умеем», у этой фразы должен быть исполняемый двойник — иначе она переживёт свою правду, и вы узнаете об этом от читателя.

Что уже починили

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

Разбор строк по образцу — самая дорогая недостача закрыта

Это была главная запись всего списка: «она одна делает нетотальными задачи 13, 14, 20, 125». Закрыта одной встроенной формой — разложить … на символы:

тотальная функция «Сколько букв»
  принимает текст: строка
  возвращает число
  пример «Три»
    дано текст равно "мир"
    ожидается 3
  «Длина списка» от (разложить текст на символы)

checkvalid: true и total: true, test — 1 из 1. Строка раскладывается в список, обход становится рекурсией по хвосту, убывание доказывается.

Насколько дорогой недостача была на самом деле, видно по тому, что сдвинулось. Лексер самоприменения self/lexer.flang стал тотальным целиком: 84 функции из 84, а было 54 из 88. У flang/stdlib/strings.flang из восьми обычных функций осталась одна. Решений LeetCode тотальны теперь 24 из 26, а было 20. Разбор — в главе «Тотальность».

Функтор, моноид, группа, изоморфизм, бифунктор — есть

В прошлой редакции здесь стояло: «нет функтора и бифунктора, нет естественного преобразования, нет монады и формы в монаде, нет моноида и группы, нет монады ввода-вывода». Из этого перечня осталось верным ровно две вещи: нет естественного преобразования и нет монады.

Всё остальное разбирается и проверяется, причём по-разному — и это отдельная история, разобранная в главе «Синтаксис по факту»: у функтора законы доказываются, у моноида проверяются на конечной сетке, а у изоморфизма не проверяются вовсе, потому что у стрелки категории нет тела.

Ввод-вывод и HTTP — есть, и язык остался чистым

Здесь стояло: «нет монады ввода-вывода — а значит, и HTTP на flang по-прежнему не пишется». Первая половина верна до сих пор, вторая — нет.

flang/examples/io/link-report.flang читает файл, ходит в сеть и пишет отчёт. Все семь её функций доказаны тотальными, все десять примеров проходят без единого эффекта. Монадой это не является, и репозиторий называет разницу прямо: продолжение не спрятано в замыкании, а объявлено значением. Разбор — в главе «Синтаксис по факту»; команда flang io — в главе «Инструмент».

Псевдонимы типов — работают

Здесь стояло: объявление разбирается, но types.mjs раскладывает объявления только на суммы и записи, и псевдоним становится записью без полей. Проверяем тип «Строка счёта» это список числаcheck даёт valid: true и total: true, пример проходит. Работает, и работает даже с подстановкой параметров типа.

Пять пунктов, снятых ещё в прошлой редакции

Их мы разбирали и раньше — связывание модулей, структурное сравнение в примерах, встроенная форма «символ», вариант как значение примера, вызов функции без аргументов, — и оставляем разбор целиком: он показывает, как выглядит проверка записи запуском, а не чтением. Все пять работают.

Связывание модулей — работает

В списке: «Заголовок „модуль … использует …“ разбирается, но связывания между файлами нет […] Стандартной библиотекой нельзя воспользоваться из решения».

На деле работает. flang/examples/import-check.flang подключает «Списки» и успешно прогоняет 46 примеров — свой один плюс сорок пять пришедших вместе с функциями стандартной библиотеки. Разбор — в главе «Стандартная библиотека».

Структурное сравнение в примерах — работает

В списке: примеры, возвращающие список или запись, «считаются провалившимися, даже когда значения совпадают поэлементно. Команда „flang test“ на таких файлах не работает».

На деле flang test flang/stdlib/lists.flang даёт 45 из 45, и среди этих примеров множество списочных.

Встроенная форма «символ» — работает

В списке: расхождение порядка аргументов между парсером и тайпчекером, «любое использование формы „символ“ не проходит check».

Проверяем:

тотальная функция «Взять символ»
  принимает текст: строка, номер: число
  возвращает строка
  пример «Второй символ»
    дано текст равно "мир"
    дано номер равно 2
    ожидается "и"
  символ номер в текст

Проходит check и test.

Вариант как значение примера — работает

В списке: parseLiteralValue «сворачивает конструктор варианта в запись из его полей и теряет имя варианта», поэтому функция, принимающая или возвращающая сумму типов, примера иметь не может.

Это же ограничение объясняет структуру flang/stdlib/optional.flang и result.flang: там половина функций помечена комментарием // Без примера: … и обложена скалярными обёртками.

Проверяем обе стороны:

тотальная функция «Есть значение»
  принимает опция: «Число или ничто»
  возвращает признак
  пример «Есть»
    дано опция равно вариант «Есть число» с значение равным 5
    ожидается да
  пример «Нет»
    дано опция равно вариант «Нет числа»
    ожидается нет
  разбор опция
    случай вариант «Есть число» с значение как зн
      то да
    случай «Нет числа»
      то нет

Оба примера проходят. Ограничение снято, но комментарии в стандартной библиотеке про него ещё стоят.

Вызов функции без аргументов — работает

В списке: «Применение записывается только как „Имя“ от аргумента, поэтому функцию с пустым списком параметров вызвать нечем».

На деле функция без параметров объявляется и вызывается — именем без от:

тотальная функция «Константа»
  возвращает число
  42

тотальная функция «Использовать»
  принимает н: число
  возвращает число
  пример «Плюс константа»
    дано н равно 1
    ожидается 43
  н плюс «Константа»

Пример проходит.

Чего действительно нет

Девять записей, и восемь из них подтверждены программой-уликой; девятая — та самая «проверка самого этого списка». Ниже каждая перепроверена нами, отдельно от улик репозитория.

Логических операций

Ни и, ни или, ни не для признаков:

$ … а и б
{"code":"FLANG_PARSE","message":"не разобрана конструкция: у функции больше одного тела"}

$ … не а
{"code":"FLANG_UNKNOWN_NAME","message":"имя «не» не связано"}

Слово и в языке занято: оно разделяет аргументы вызова и поля конструктора. Конъюнкция пишется вложенными если, отрицание — сравнением равен нет. Читается заметно хуже написанного условия — так и записано в списке.

Образцов для строк — то, что осталось от самой дорогой недостачи

Запись в каталоге сохранилась, но похудела, и её новая формулировка — образец того, как надо переписывать такие вещи:

Разложение строки в список появилось — форма «разложить … на символы», и это закрыло самую дорогую недостачу: задачи 13, 14, 20 и 125 стали тотальными. Осталось меньшее: образцов для строк по-прежнему нет, «пусто» и «голова и хвост» работают только со списком, поэтому посимвольный проход всегда идёт через разложение, а не напрямую.

То есть недостача не исчезла, а уменьшилась, и запись говорит ровно то, что осталось. Проверяется это уликой: программа с разбор текст / случай пусто / случай голова и хвост по-прежнему не проходит.

Насколько дорогой недостача была, лучше всего видно по тому, что осталось от таблицы, которая стояла здесь в прошлой редакции. Она объясняла нетотальность пяти слоёв компилятора одной причиной, и первая её строка была self/lexer.flang — 34 обычные функции из 88. Сегодня в этом файле обычных функций ноль. Полностью сдвинулись три строки из пяти; две не сдвинулись вовсе, и это не случайность — у types.flang и totality.flang причина всегда была другая, и в таблице она была названа отдельно:

AST приезжает в эти слои обобщённым значением JSON, а не своей суммой типов, и «поле, найденное по ключу» анализ частью значения не считает.

Вот ради чего проект ведёт список долгов с причинами, а не с жалобами: когда причину закрывают, сразу видно, какие именно строки должны были сдвинуться. Если бы все пять были свалены в «сложный код», проверить починку было бы нечем. Актуальные числа — в главе «Тотальность».

Диагностики для варианта, названного ключевым словом

Само ограничение честно описано в flang/SPEC.md, раздел 10: лексер решает, что перед ним, до того как становится известен тип, поэтому вариант с именем Да, Плюс или Больше в образце не разбирается. Проверяем:

тип «Ответ»
  вариант Да
  вариант Нет
{"code":"FLANG_TYPE","message":"образец-литерал имеет тип признак,
 а разбирается «Ответ»","severity":"error","span":null}

Обходится это переименованием либо явной формой случай вариант «Да», которой пользуется стандартная библиотека, — с ней тот же файл проходит check без диагностик. Но обратите внимание на сообщение: оно не называет настоящую причину. Спецификация это признаёт и записывает долгом — «сообщение обязано говорить „имя варианта совпадает с ключевым словом“, а не „ожидался образец“», — и отдельно уточняет, что ограничение не связано со связыванием модулей, при котором его нашли: тот же код в одном файле ведёт себя так же.

Ещё одна деталь: span здесь null, то есть места отказа диагностика не называет вовсе. На фоне остальных сообщений языка, где место есть всегда, это заметно.

Убывания по мере

Анализ завершаемости знает только структурное убывание. n − 1, алгоритм Евклида, двоичный поиск по границам — всё FLANG_NOT_TOTAL, хотя завершается очевидно. Разбор — в главе «Тотальность».

Словаря и множества

Нет ни ассоциативного массива, ни множества. Каждая задача «посчитай, сколько раз встретилось» превращается из O(n) в O(n²). В решении про анаграммы вместо словаря — список записей и линейный поиск по ключу, с прямо посчитанной ценой: «O(слов × групп × 26) вместо O(суммарной длины)».

Индексного доступа

Список читается только с головы; «Элемент по номеру» пишется рекурсией и стоит O(n). Кучи, таблицы динамики и двумерные сетки на этом ломаются.

Порядка на строках

{"code":"FLANG_TYPE","message":"левый операнд сравнения «gt» имеет тип строка:
 сравнения порядка допустимы только для чисел"}

Сортировка строк невыразима. Уточнение к списку: там этот пункт описан как расхождение слоёв, при котором программа проходит проверку и падает при запуске. Сейчас отказ приходит на check — то есть до запуска. Само ограничение осталось, диагностика стала лучше.

Параметрического полиморфизма — и здесь запись отстала от собственной улики

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

В каталоге записано:

«Обратить» для списка числа и для списка строки — две разные функции с одинаковым телом. Опциональное значение приходится заводить отдельно под каждый тип, а имена вариантов обязаны быть уникальны в модуле.

Улика при этом проверяет не это. Она берёт два непараметрических типа с одинаковыми именами вариантов и требует, чтобы компилятор их отверг:

$ node flang/bin/flang.mjs check дубль.flang
FLANG_TYPE — вариант «Есть» объявлен и в «Возможно», и в «Двойное»:
             имена вариантов должны быть уникальны

Это правда. Но ту же задачу язык сегодня решает параметрически, и наш прогон это показывает:

$ node flang/bin/flang.mjs check полиморфизм.flang
{ "valid": true, "types": ["Возможно"] }

Одно объявление тип «Возможно» от «А» обслуживает и «Возможно» от числа, и «Возможно» от строки, и «Возможно» от («Возможно» от числа). Три примера проходят. То есть первая половина записи — про то, что «Обратить» под каждый тип пишется заново, — про язык уже неправда; правдой она осталась только про репозиторий, где ни stdlib, ни examples не вправе пользоваться полиморфизмом, пока его не понимает self/parser.flang.

Соседняя запись оформлена именно так, и её заголовок стоит прочитать внимательно: «функции первого класса в программах репозитория». Там разделение проведено, и улика двойная — эталон обязан программу принять, а парсер на flang отказать. У полиморфизма такого разделения нет, и запись говорит шире, чем её улика.

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

Подробнее про сам полиморфизм — глава «Система типов».

Функций первого класса — в программах репозитория

Запись нового вида, и вид этот стоит отметить: она про разрыв между языком и его репозиторием, а не про язык.

У языка функции первого класса есть: значение-функция строится, применение проверяется по типам и арности, завершаемость доказывается на высшем порядке, и все восемь целей печатают это дефункционализацией. Пользоваться ими ни stdlib, ни examples не вправе: self/parser.flang новой формы не разбирает, а корпус сверки самоприменения собирается по маске каталога — первый же такой файл роняет неподвижную точку.

Улика поэтому двойная и требует обеих половин сразу: эталон обязан программу принять (иначе запись означала бы не то, что написана), а парсер на flang — отказать. Совпадут — тест покраснеет и скажет, что запись пора убрать.

Это самая аккуратная запись во всём списке, и образец того, как надо формулировать недостачу растущего проекта: назвать не «чего нет», а у кого именно этого нет.

Обработки ошибок

Отказ встроенной формы прекращает вычисление целиком и не перехватывается. Проверять пригодность аргумента приходится заранее, «а выразить эту проверку удаётся не всегда».

Литерала записи

$ … дано поз равно {цена: 10, количество: 3}
{"code":"FLANG_PARSE","message":"не разобрана конструкция: неожиданное '{'"}

Записи строятся только конструктором запись «Имя» с поле равным ….

Двух встроенных форм, до которых не добраться

пусто в позиции выражения всегда читается как литерал пустого списка, поэтому до одноимённой формы (проверка «список или строка пусты») из исходника не добраться — пишется (длина x) равен 0. Аналогично соединить X с Y всегда даёт склейку двух строк, а списочная форма из builtins.mjs недоступна; в flang/stdlib/strings.flang она написана заново.

Изменяемого состояния и объектов с методами

По устройству языка. Из-за этого невыразимы целые классы задач — в разделе «невыразимые» это LRU Cache и Min Stack: «задача формулируется как API из четырёх операций над разделяемым состоянием».

Монады и естественного преобразования

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

$ node flang/bin/flang.mjs check м.flang
{"error":"не разобрана конструкция: неожиданное 'монада'", …}

Причина названа в контракте и не сводится к «руки не дошли». Монада — эндофунктор плюс два естественных преобразования, а соединение требует M(M(A)). Параметры типа для этого появились, но само преобразование — четвёртый шаг контракта, и монада стоит после него. Разбор — в главе «Синтаксис по факту».

Из-за этого ввод-вывод сделан не монадой: продолжение объявлено значением, а не спрятано в замыкании. Что именно за это отдано, репозиторий перечисляет четырьмя пунктами, и все четыре видны в коде примера.

Доказательств свойств для всех входов — и не будет без отдельной большой работы

Названо в контракте прямо: для этого нужен либо SMT-решатель (тогда доказуемы линейная арифметика и равенства, но не всё), либо зависимые типы (тогда доказательство пишет автор, и язык перестаёт быть простым). Пока нет ни того ни другого, документация обязана говорить «проверено на N входах», а не «доказано».

Формулировку, которую контракт предписывает и себе, и курсу, мы теперь обязаны уточнить — она стала на слово длиннее, и это слово важное:

завершение доказано, типы доказаны, законы проверены — при компиляции на сетке, при выполнении на фактических данных.

И даже эта формулировка огрубляет. Внутри одной конструкции граница проходит посередине: у моноида устройство доказывается, а законы проверяются; у изоморфизма законы не проверяются вовсе, потому что у стрелки нет тела. Разбор — в главе «Синтаксис по факту», раздел «Граница доказано / проверено проходит внутри одной конструкции». Это, пожалуй, главное, что стоит унести из всего трека: слово «доказуемый» на титульной странице языка означает по меньшей мере три разных уровня уверенности — доказано для всех входов, проверено на конечной сетке, не проверяется вовсе, — и различать их приходится самостоятельно, потому что называются они одинаково.

Чего нет вокруг языка

Отдельный список, не менее важный при оценке.

Подсветки синтаксиса — пункт закрыт. В прошлой редакции здесь стояло, что каталог editors/ — весь про .fts, а для .flang подсветки нет ни одной. Сегодня в editors/ нет ни tree-sitter, ни лексера Chroma, зато есть грамматика TextMate vscode/syntaxes/flang.tmLanguage.json со scopeName: source.flang, подсветка Vim vim/syntax/flang.vim и заготовка записи Linguist linguist/languages-flang.yml — всё для .flang. Старый проект FTS вынесен из репозитория целиком (коммит fdfb0aa, 16 августа 2026: 357 файлов, 180 755 строк), и вместе с ним ушёл tools/ftsls, о котором говорила прошлая редакция.

LSP, форматирования, линтера. Половина пункта закрылась. В editors/ появился каталог flang-lsp, а в package.json — вторая команда:

"bin": { "flang": "./packaging/flang-launch.mjs", "flang-lsp": "./flang/bin/flang-lsp.mjs" }

Сервер даёт ту же диагностику, что flang check — тем же кодом и тем же текстом, — плюс дополнение, сигнатуру при наведении и переход к объявлению. Клиент теперь тоже есть, хотя прошлая редакция говорила, что его «намеренно нет»: editors/vscode/extension.js, 46 строк, которые только запускают сервер и передают слова протокола — «в нём нет ни одного знания о языке».

Порядок, в котором это появлялось, всё же остаётся занятным: сервер пришёл раньше подсветки. Обычно бывает наоборот, и причина не случайна — грамматика раскрашивает текст, ничего о нём не зная, а сервер знает про файл всё, потому что переиспользует настоящий компилятор.

fmt по-прежнему нет: команда заявлена в разделе 6 спецификации, CLI отвечает unknown command 'fmt'. Отказ записан и объяснён — «переименование, правки, форматирование: их нет и не обещано, это была бы вторая реализация языка рядом с первой».

Выпущенного пакета — пункт закрыт. В прошлой редакции здесь стояло, что тег v0.4.0 поставлен, а в реестре пусто, и «между тегом и реестром стоит ещё один шаг». Шаг сделан:

$ brew info digitable-lol/tap/flang
==> digitable-lol/tap/flang: stable 0.6.2

Теги в origin дошли тогда до v0.4.5, формула Homebrew ссылалась на тот же релиз, и номера сошлись во всех трёх местах сразу — чего не было ни в одной из предыдущих редакций этой главы. Отдельного пакета для языка тогда ещё не было: он ехал внутри пакета FTS.

Замеров производительности. Стенд в benchmarks/ меряет компиляцию и валидацию FTS-модели. Ни интерпретатор flang, ни сгенерированный им код в репозитории не измерены.

Руководства и туториала. README за сутки переписали ещё дважды, и жанр у него сменился: вместо пересказа языка словами там теперь одна и та же функция показана исходником на flang и рядом тем, во что она печатается в C, Go, Rust, Python и JavaScript, — фрагменты вставлены из настоящих прогонов flang emit, а не набраны руками. Русская редакция при этом догнала английскую и переросла её: 718 строк против 632, двенадцать разделов против одиннадцати, и лишний — про компилятор в flang/self/, которого на английской странице пока нет. Но это по-прежнему README, а не руководство, и его редакции успевают отменять друг друга — раздела «How FTS and flang relate», который был в нём вчера, сегодня уже нет. Каталог docs/ в корне — про FTS; у самого flang есть SPEC.md, core/SPEC.md, self/SPEC.md, комментарии в исходниках и index.json. Пути «от нуля до своей программы» не написано.

Сообщества и пользователей. Репозиторий создан 3 августа 2026 года.

Как этим пользоваться

Список выше — не приговор, а срез. И вот главное число этой главы: из шестнадцати записей прошлой редакции сегодня осталось девять, а из пятнадцати записей самого каталога восемь пришлось выбросить как неправду. Не как устаревшее — как неправду.

Это не риторическая фигура, и мы наблюдали её пять раз. Пока трек готовился к публикации, у языка появились два новых бэкенда кодогенерации, а парсер ядра FTS на flang научился разбирать скобочный диалект и сошёлся с эталоном на всём корпусе. Ещё через несколько часов началось самоприменение: на flang написали лексер, парсер и печать в C для самого flang, а пакет подготовили к выпуску. Ещё через несколько — слоёв стало пять, а печать в C дозрела: научилась экранировать двунаправленные символы и считать шаги, из-за чего абзац про «в C лимита шагов нет» в соседней главе пришлось переписать на обратный (глава «Кодогенерация»). Каждый абзац этой главы пришлось перепроверять запуском четырежды. index.json при этом не менялся вовсе, то есть отстал ещё сильнее.

Четвёртая волна пришла ещё через несколько часов и впервые задела не язык, а то, что вокруг него: починился конвейер публикации, пакет сменил имя, поставили тег v0.4.0, а тесты снова пошли на Node 20 — где семь файлов до того не загружались вовсе, и в матрице CI шло 920 случаев вместо 1277 (глава «Как читать репозиторий»). Перечень выше от этой волны не сдвинулся ни на пункт, и это тоже сведение: язык и его обвязка стареют с разной скоростью, а список недостач языка живёт по своему календарю.

И одна поправка, которую эта волна заставила внести задним числом. В соседней главе стояло, что каталог flang/self в поставку не входит: так читался список files в package.json. Мы прочитали список и не упаковали пакет — а npm pack показывает flang/self внутри, и это 1232 КБ, крупнейшая часть тарбола. Ошибка жила с той минуты, как была написана, и пережила три волны проверок ровно потому, что проверялась чтением. Здесь это стоит повторить: перечень намерений и состав результата — разные вещи, и вторая узнаётся только запуском.

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

Отсюда практический совет: не верьте ни этой статье, ни index.json, а проверьте запуском. Цикл короткий — node flang/bin/flang.mjs check файл.flang работает без установки и без сборки, а отказ приходит с кодом, сообщением и позицией. Три минуты на проверку надёжнее любого текста о суточном языке, включая этот.

И общее наблюдение об оценке молодых технологий, ради которого эту главу стоит дочитать до конца.

Полезнее всего оказался не список возможностей, а список недостач, который проект ведёт сам. Но польза эта хрупкая, и хрупкость её теперь измерена: за сутки такой список стал наполовину выдуманным, и заметить это было нечем, потому что утверждение о недостаче — единственное, которое не ломается, когда становится ложным. Против этого работает ровно одна вещь — программа-улика: исполняемый двойник каждой фразы «мы этого не умеем», который краснеет, когда фраза перестаёт быть правдой.

Оценивая проект, поэтому, спрашивайте не «есть ли у них список ограничений», а «чем этот список проверяется». У flang ответ есть, и он лежит в flang/test/missing.test.mjs. Мы нашли в нём одну запись, где улика говорит уже, чем сама запись, — и это не опровержение приёма, а первая же демонстрация того, для чего он нужен: без улик мы бы не нашли ничего, потому что и сравнивать было бы не с чем.

Дальше — глава «Как читать репозиторий», про то, как в этом разбираться дальше.

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов
Дальше