Skip to content

«Манифест дизайна YaoXiang» — резкая критика ​

Версия: v2.0.0 (в конце концов, «официально опубликованный» черновик — тоже публикация)
Статус: мысленный оргазм
Автор: Чэньсюй + ещё не собранное «сообщество»
Дата: 2026-05-31 (из будущего, но компилятор всё ещё вчерашний)


«Дао рождает единое, единое рождает двойственное, двойственное рождает тройственное, тройственное рождает все вещи.»
— «Дао дэ цзин»

Типы — это Дао, все вещи рождаются из них.
(Программисты — как муравьи, все суетятся из-за них.)


I. Зачем создавать YaoXiang? — Потому что миру явно не хватает 514-го языка ​

1.1 Заполняемый пробел в языках ​

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

ПотребностьПроблема существующих решенийНаше решение (предположительно)
ТипобезопасностьRust слишком строг, TypeScript слишком мягокМы создадим квантово-суперпозиционную систему типов — одновременно строгую и расплывчатую
Естественный синтаксисЧужие синтаксисы неестественныНаш синтаксис будет настолько естественным, что вы забудете, что программируете (возможно, потому что не поймёте, что написано)
Дружелюбие к ИИИИ часто ошибается при генерации кодаМы спроектируем синтаксис для ИИ; людям тоже можно будет пользоваться

1.2 Решаемые практические проблемы ​

Проблема первая: фрагментация системы типов
Мы выдвигаем тезис «всё есть тип», что решает неприятную философскую проблему «некоторые вещи не являются типами». Теперь даже отступ в вашем коде может быть типом (IndentationLevel<4>).

Проблема вторая: выбор между безопасностью памяти и производительностью
Мы изначально взяли модель владения из Rust, но обнаружили, что «анализатор заимствований» слишком сложно реализовать. Тогда нас осенило — переименуем &T и &mut T из «ссылок» в «токены» и объявим их «доказательствами прав доступа нулевого размера на этапе компиляции». Теперь анализатор заимствований не нужен — достаточно «потокочувствительного анализа живости» — звучит совершенно по-другому, правда? Если в программе гонка данных, значит, проблема в механизме брендирования токенов.

Проблема третья: когнитивная нагрузка асинхронного программирования
Мы заново изобрели колесо и назвали его «моделью параллельного творения (并作)». Достаточно одного spawn — и компилятор автоматически обработает все асинхронные детали. Если не обработает — значит, ваш код написан недостаточно «параллельно-творчески».

Проблема четвёртая: узкие места ИИ-ассистированного программирования
Мы заботливо спроектировали для ИИ строгие отступы и чёткие границы, чтобы GPT-7 не сходил с ума при генерации кода. Что касается того, поймёт ли это человек-программист... это второстепенно.

1.3 Философские корни языка ​

Название YaoXiang происходит из «И цзин», что гарантирует ему встроенный мистический бафф в технических дискуссиях. Когда код не компилируется, можно сказать: «Это инь и ян не в гармонии, надо бы погадать».


II. Основная философия и принципы — непреложные священные заповеди ​

2.1 Принцип первый: всё есть тип ​

Непреложная причина: так мы сможем объяснить через теорию типов всё, включая причину вечных задержек проекта.

2.2 Принцип второй: строгая структурированность ​

Непреложная причина: 4 пробела для отступа — космическая истина. Тех, кто использует табы, следует сослать на Марс.

2.3 Принцип третий: абстракции с нулевой стоимостью ​

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

2.4 Принцип четвёртый: неизменяемость по умолчанию ​

Непреложная причина: изменяемость — корень всего зла. Если вам нужно изменить переменную, значит, ваш дизайн ошибочен.

2.5 Принцип пятый: тип — это данные ​

Непреложная причина: так мы сможем проверять типы во время выполнения, а потом обнаружим... что уже проверили их во время компиляции.


III. Ключевые инновации и особенности — повторное изобретение уже изобретённого ​

3.1 Инновация первая: унифицированный синтаксис типов ​

Мы упразднили сбивающие с толку концепции enum, struct, union, trait, impl, а затем упразднили и само ключевое слово type. Теперь всё использует форму name: Type = value. Запомните: Type — это не ключевое слово — это зарезервированное слово, и не спрашивайте, в чём разница.

3.2 Инновация вторая: конструктор — это тип ​

Устранена пропасть между «типом» и «значением», создана новая пропасть: «это конструктор типа или конструктор значения? А, подождите, теперь у них одинаковый синтаксис — стало ещё непонятнее».

3.3 Инновация третья: каррирование привязки методов ​

Мы реализовали вызов методов через каррирование. Теперь вы можете использовать Type.method = function[0] вместо параметра self. Очевидно, интуитивнее. [0] означает «считать нулевой аргумент self»; если забыли написать [0], компилятор скажет: «Это не метод, это обычная функция». Просто!

3.4 Инновация четвёртая: модель владения (RFC-009 v9) ​

Пять концепций, один градиент: &T, &mut T, Move, ref, clone(), unsafe. Стоп, это шесть. Неважно — &T и &mut T — это «токены», а не «ссылки». В чём разница? Ссылки — это концепция из C++, токены — это типоуровневые доказательства прав доступа нулевого размера на этапе компиляции. Когда ваш код не компилируется, вы можете сказать: «Вывод атрибута типа Dup/Linear не удался» — никто не посмеет возразить.

Система токенов также включает эти продвинутые функции:

  • freeze: «замораживает» &mut T в &T. Как положить свежие продукты в холодильник — готовить нельзя, пока не разморозишь. Компилятор отслеживает состояние заморозки через «потокочувствительный анализ живости» — звучит как монитор в реанимации.
  • Механизм брендов: каждому токену на этапе компиляции присваивается уникальное целое число (бренд #N) для защиты от подделки. «Извините, сэр, бренд #42 вашего токена &Point не совпадает с брендом #43 в капсуле владельца».
  • Невозможность переноса между задачами: токены — это «доказательства прав доступа на этапе компиляции» и не могут пересекать потоки. Если нужно разделить между задачами, используйте ref. Почему? Потому что компилятор сказал «нет». На самом деле потому, что токены исчезают после компиляции — тип нулевого размера, нулевые накладные расходы в рантайме, нулевые возможности межзадачного разделения.

Итог: Rust объясняет анализатор заимствований на 200 страницах The Book. YaoXiang объясняет всё фразой «&T копируемо, &mut T — нет». Простота — это красота.

3.5 Инновация пятая: модель «параллельного творения» — самая паршивая часть языка ​

«Все вещи творятся параллельно, я наблюдаю их возвращение.» — «И цзин», гексаграмма Фу (Возврат)

Главный козырь модели «параллельного творения»: синхронный синтаксис, асинхронная суть. Переводя на человеческий: ваш код выглядит как последовательное выполнение, но в рантайме автоматически становится параллельным. Когда именно? Как? Решает компилятор. Это не модель конкурентности — это игра в доверие.

Посмотрим, что мы напихали в язык ради этой магии:

Ключевое слово spawn: помечает функцию как асинхронную. Заметьте — не async, а spawn. Потому что async слишком мейнстрим. Но в Rust spawn означает «запустить задачу». Ничего, переопределим.

Аннотация @block: помечает spawn-функцию для «синхронного выполнения». Подождите — если spawn — это асинхронно, а @block делает её синхронной, то почему бы просто не убрать spawn? «Потому что иногда spawn-функция должна синхронно выполняться в некоторых контекстах». То есть функция, помеченная spawn, может быть и асинхронной, и синхронной — в зависимости от настроения вызывающего. Это не система типов, это раздвоение личности.

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

Итог по трём аннотациям модели конкурентности:

spawn  = эта функция будет асинхронной (если не @block)
@block = эта spawn-функция в этот раз будет синхронной (перекрывает spawn)
@eager = это выражение в будущем не будет лениво вычислено (пока не обращай внимания на будущее)

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

3.6 Инновация шестая: зависимые от значений типы (RFC-011) ​

Теперь вы можете на этапе компиляции доказать, что длина массива — простое число, размерности матриц совпадают, а результат factorial(5) можно использовать в сигнатуре типа. Это бесполезно для бизнес-логики, но «тип — это утверждение, программа — это доказательство» — круто же, да?

3.7 Инновация седьмая: минималистичный дизайн ключевых слов ​

Всего 17 ключевых слов! На 8 меньше, чем в Go! Хотя смысл каждого ключевого слова в 3 раза сложнее, чем в Go, по количеству мы победили. Заметьте: type — не ключевое слово — оно было удалено в RFC-010. Теперь вы используете name: Type = value, где Type — зарезервированное слово. В чём разница между ключевым и зарезервированным словом? Не спрашивайте, это вопрос внутренней космической иерархии Type0/Type1/Type2 компилятора.

3.8 Инновация восьмая: изоморфизм Карри-Ховарда — универсальный метод объяснения ​

Когда кто-то ставит под сомнение дизайнерское решение, стандартный ответ: «Это следует из изоморфизма Карри-Ховарда». Не понимаете? Ничего, в сообществе никто по-настоящему не понимает. В двух словах: «тип — это утверждение, программа — это доказательство», так что ваш код — не просто программа, а математическая статья. Ошибка компиляции — это доказательство от противного.

Венец этой философии — пасхалка в RFC-010: Type: Type = Type. Попробуйте скомпилировать эту строку — компилятор не упадёт, он выведет дзен-сообщение примерно такого смысла: «Дао, которое может быть названо, не есть вечное Дао; тип, который может быть типом, не есть вечный тип». Это дань уважения YaoXiang парадоксу Жирара и единственная функция, которую компилятор намеренно не реализует. Мы называем это «границей языка» — когда вы её достигаете, компилятор здесь умолкает, а философия задерживается.


IV. Предварительный обзор синтаксиса — «вроде бы работающий» пример кода ​

yaoxiang
# === Hello World (可以在脑中运行) ===
main: () -> Void = {
    print("Hello, 未来的贡献者!")
}

# === 所有权模型:五个概念(其实是六个) ===
Point: Type = { x: Float, y: Float }

p1 = Point(1.0, 2.0)
p2 = p1              # Move。p1 安息吧。
p2.print()           # 编译器创建 &Point 令牌。令牌品牌 #4201,请查收。
p2.shift(1.0, 1.0)  # 编译器创建 &mut Point 令牌。独占!其他令牌退避!
shared = ref p2      # ref = 共享。编译器自动选 Rc。或者 Arc。你不需要知道。
backup = p2.clone()  # 深拷贝。为什么不用 ref?因为 ref 不是拷贝,是共享。懂?

# === 统一语法:name: type = value ===
# 你能看出下面哪个是类型,哪个是函数,哪个是变量吗?
# 答案:看不出来。这就是"统一"的美。
identity: (T: Type) -> ((x: T) -> T) = x
List: (T: Type) -> Type = { data: Array(T), length: Int }

# === 值依赖类型:把阶乘写在类型签名里 ===
factorial: (n: Int) -> Int = {
    # 编译器自动分析参数递减,不需要任何注释
    if n <= 1 { return 1 }
    return n * factorial(n - 1)
}
arr: Array(Int, factorial(5)) = Array(Int, 120)()  # Array(Int, 120) 类型,编译期计算

# === 并作模型:spawn + @block + @eager = 三位一体的混乱 ===
fetch_data: (url: String) -> JSON spawn = {
    return HTTP.get(url).json()
}

@block  # 这一行让上面的 spawn 函数在这调用时变成同步的
main: () -> Void = {
    data = fetch_data("https://api.example.com")  # 同步?异步?看心情。
}

# @eager:标记"将来惰性求值实现后不要惰性求值这里"
result: Int eager = heavy_computation()  # 目前跟没写一样

# 总结:
# spawn = 异步(除非 @block)
# @block = 把 spawn 变同步
# @eager = 将来不做某事(现在什么都没发生)
# 三个概念加起来 = if else

Приведённый код отлично работает в документе. Реальный результат компиляции может отличаться. Нет, точно отличается.


V. Дорожная карта и нерешённые вопросы — список мечтаний ​

5.0 Треугольник зависимостей RFC ​

Прежде чем узнать дорожную карту, полюбуйтесь на самое изящное архитектурное решение YaoXiang — любовный треугольник RFC:

RFC-009 (владение)  →  зависит от RFC-010 (унифицированный синтаксис)  →  зависит от RFC-011 (generics)
    ↑                                                          │
    └───────────────────── зависит ───────────────────────────┘

009 нуждается в синтаксисе из 010, 010 нуждается в generics из 011, 011 нуждается в системе типов из 009. Три RFC взаимно предполагают друг друга. Какой реализовывать первым? «Рекомендуется реализовать синхронно». — строка 141 RFC-010.

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

5.1 Принятые дизайнерские решения ​

Больше не принимаются изменения, если только мы не передумаем.

5.2 Обсуждаемые дизайнерские вопросы ​

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

5.3 Дорожная карта реализации ​

v0.1: интерпретатор на Rust          ✅
v0.5: компилятор байткода            🔄 (в процессе, уже 18 месяцев)
v1.0: готовность к продакшену        ⏳ (когда найдём 10-го контрибьютора)
v2.0: самохостинг                    ⏳ (когда в v1.0 решим проблему путешествий во времени)

5.4 Текущее состояние реализации ​

  • Лексер: ✅ 100% (может распознать слово spawn)
  • Парсер: ✅ 100% (может разобрать, что после spawn должно быть что-то)
  • Проверщик типов: ✅ 95% (может определить, что 42 имеет тип Int, но космический уровень Type всё ещё обсуждается)
  • Система токенов владения: ✅ 100% (документ дизайна готов. Реализация? Это следующий шаг.)
  • Документация RFC: ✅ 14 приняты (в среднем 800 строк каждая. Код? Какой код?)
  • Реально работающий код: 🔴 0%

VI. Как участвовать в разработке — захватите время, энтузиазм и заниженные ожидания ​

В Cargo.toml в разделе authors: ["YaoXiang Team", "ChenXu2333"]. Team и ChenXu2333 стоят рядом. Исследование показало, что текущий размер Team — 1 человек. Но множественное число слова «Team» дарит бесконечный простор для воображения.

6.1 Дизайн-дискуссии ​

Подходит для: людей, любящих теоретически спорить о том, является ли монада моноидом в категории эндофункторов.

6.2 Реализация компилятора ​

Подходит для: тех, у кого есть запасные нейроны и кого не смутит их использование для реализации 7-й модели управления памятью.

Сейчас больше всего нужны контрибьюторы для:

  • Обнаружение конфликтов токенов: реализация «потокочувствительного анализа живости». Не пугайтесь названия, принцип прост — отслеживать состояние каждого токена в теле функции: активен, заморожен, перемещён. Как отслеживать трёх детей на игровой площадке. Только дети могут бесконечно рекурсировать.
  • Lint обнаружения циклов между задачами: обнаружение циклических ссылок ref между задачами. По умолчанию warn, можно настроить на deny. Нужно решить, насколько суровым должно быть предупреждение: «Warning: cross-task cycle detected» или «Warning: ваш код образовал межзадачный цикл; утечек не будет, но вам должно быть стыдно»?

6.3 Разработка инструментария ​

Нужно разработать: LSP-сервер, отладчик, форматтер, менеджер пакетов... всё. Особенно LSP — когда пользователь наводит курсор на Type: Type = Type, должна появляться всплывающая подсказка «Невыразимое».

6.4 Создание стандартной библиотеки ​

От std.io до std.gui — всё будет. Сейчас есть: std.placeholder. Следующий план: std.placeholder_v2.

6.5 Перевод документации ​

Нам нужно перевести 14 RFC на английский. В среднем 800 строк каждая. Итого ~11200 строк. Учитывая, что RFC наполнены такими понятиями, как «并作», «爻象», «万物并作吾以观复», это примерно эквивалентно переводу половины «Дао дэ цзин». Записывайтесь скорее.

6.7 Руководство контрибьютора ​

Формат commit-сообщений: должен быть стихотворением. Сонет предпочтительно. Хайку тоже принимается:

Токен владения
После компиляции исчез
Абстракция без цены

Приложение C: Часто задаваемые вопросы ​

В: Какие преимущества YaoXiang по сравнению с Rust?
О: Меньше синтаксического сахара! Меньше ключевых слов! Меньше полезных функций! Зато больше философской глубины. К тому же у нас есть «система токенов заимствования» — звучит же круче, чем «анализатор заимствований», правда?

В: Для каких задач подходит YaoXiang?
О: Для разработки компилятора YaoXiang. А также для написания манифестов и RFC. Остальные применения — предмет исследований.

В: Почему выбран отступ в 4 пробела?
О: 2 — слишком плотно, 8 — слишком разреженно, 4 — золотая середина, в духе «И цзин».

В: Type — это ключевое слово?
О: Нет. Это «зарезервированное слово». Разница между ключевым и зарезервированным словом: ключевые слова попадают в список ключевых слов в спецификации языка, зарезервированные — в список «внимание: нижеследующее — не ключевые слова». Просто и понятно.

В: Почему 14 принятых RFC, а версия всё ещё 0.7.0?
О: Потому что мы играем по-крупному. Сначала дизайн, потом реализация. Очень «потом».

В: ref — это Rc или Arc?
О: Компилятор выбирает автоматически. Не ваша забота. По сути, это единственный случай, когда компилятор умнее пользователя, и мы полностью ему доверяем.

В: Когда «модель параллельного творения» заработает по-настоящему?
О: Когда вы читаете эти строки, ответ по-прежнему: «стадия дизайна, не реализовано». Но ключевое слово spawn уже корректно парсится — разве это не воодушевляет?

В: Когда выйдет версия 1.0?
О: Когда «сообщество» вырастет с 1 до 2 человек.

В: Как связаться с ключевой командой?
О: Оставьте сообщение в GitHub Discussions. Время ответа: 1–3 рабочих месяца.


VII. Дальнейшая ложь ​

«Поддержка множества языков»: docs/src/{en,ja,ru,zh} — все четыре языка на месте. Компилятор v0.7.0, реально работающего кода около нуля строк, но японские и российские разработчики уже могут читать на родном языке про «модель параллельного творения» и «зависимые от значений типы». Это классическая «разработка через документацию» — сначала дайте всему миру понять ваш дизайн, потом притворяйтесь, что он кому-то нужен. Когда компилятор сможет запустить Hello World, документацию уже переведут на клингонский.

Матрёшка инструментария: pre-commit на Python проверяет стиль кода на Rust (cargo fmt + clippy), компилятор на Rust компилирует исходники YaoXiang. Три слоя языков друг на друге, каждый зависит от следующего. Когда YaoXiang захостит сам себя, матрешка станет такой: Python проверяет Rust, Rust компилирует YaoXiang, YaoXiang компилирует YaoXiang. Тогда при падении любой upstream-зависимости весь инструментарий превратится в перформанс. Но это неважно — само слово «самохостинг» стоит двух RFC.

YaoXiang-book.md: книга, систематически описывающая язык YaoXiang. Написать книгу для описания ещё не реализованного языка программирования — это как издать путеводитель по несуществующему городу. «Глава третья: система generics — код в этой главе не компилируется, но синтаксически корректен. Пожалуйста, представьте результат выполнения». Самая честная фраза во всей книге — «стадия проекта: экспериментальная проверка» на первой странице.

«Без GC»: официальная позиция: «YaoXiang без GC». Строго говоря, у нас нет tracing GC. Но ref в рантайме — это подсчёт ссылок (Rc/Arc). Считается ли подсчёт ссылок GC? «Нет. GC — это garbage collection, а подсчёт ссылок — automatic reference counting. Видите, сокращения разные. Одно — GC, другое — ARC. Совершенно разные вещи». Смысл этой словесной игры в том, что когда кто-то скажет «так у вас же подсчёт ссылок, это GC!», можно с праведным видом ответить: «Нет, у нас нет GC, только автоматически управляемый компилятором подсчёт ссылок». В чём разница? На слайдах презентации.

Последнее обновление: 2026-05-31 (возможно, последнее, но кто знает)

Версия документа: v2.0.0 (мы быстро прыгаем по версиям, так прогресс выглядит внушительнее)

Лицензия: MIT (пока есть только файл MIT)


«Яо и сян преображаются, и все вещи рождаются. Типы эволюционируют, программы создаются.»

Пусть путь дизайна YaoXiang станет для вас любимой темой для бесед за чашкой чая.
__(Ведь на данном этапе он в основном и есть тема для бесед.)_**