«Манифест дизайна 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. Предварительный обзор синтаксиса — «вроде бы работающий» пример кода
# === 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 станет для вас любимой темой для бесед за чашкой чая.
__(Ведь на данном этапе он в основном и есть тема для бесед.)_**
