Skip to content

《Манифест дизайна YaoXiang》: Критический обзор

Версия:v2.0.0(毕竟"正式发布"的草稿也是发布) 状态:Интеллектуальный оргазм 作者:晨煦 + «сообщество», которое ещё не сформировалось 日期:2026-05-31(来自未来,但编译器还在昨天)


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

Типы — как Дао, всё рождается из них. (程序员如蝼蚁,皆由此卷。)


一、Зачем мы создали YaoXiang?—— Потому что миру явно не хватало 514-го языка

1.1 Лакуны, которые мы заполняем

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

ПотребностьПроблемы существующих решенийНаше решение(ожидаемое)
类型安全Rust слишком строгий, TypeScript слишком мягкийМы создадим типовою систему в квантовом суперпозиционном состоянии — одновременно строгую и нестрогую
自然语法Чужая syntax везде неестественнаНаш синтаксис будет настолько естественен, что вы забудете, что программируете(или не поймёте, что читаете)
ИИ-дружелюбиеИИ часто ошибается при генерации кодаМы разработали синтаксис специально для ИИ, люди могут тоже пользоваться

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

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

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

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

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

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

Имя YaoXiang происходит из «И Цзин», что гарантирует ему мистический ореол в технических дискуссиях. Когда код не компилируется, можно сказать: «Это инь и ян ещё не в гармонии, дайте-ка я погадаю.»


二、Ключевая философия и принципы —— Неоспоримые священные писания

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

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

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

Некомпромиссная причина:4 пробела — это истина вселенной. Люди, использующие Tab, должны быть сосланы на Марс.

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

Некомпромиссная причина:Хотя у нас 7 уровней абстракции, поскольку они «нулевой стоимости», производительность должна быть примерно как у ассемблера… теоретически.

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

Некомпромиссная причина:Изменчивость — корень всех зол. Если вам нужно изменить переменную, значит, вы неправильно спроектировали.

2.5 Принцип пятый: Типы как данные

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


三、Ключевые инновации и особенности —— Изобретаем уже изобретённое

3.1 Инновация первая: Унифицированный тип syntax

Мы упразднили эти сбивающие с толку концепции как 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), используемое для защиты от подделки. «Извините, сэр, ваш токен &Point с брендом #42 не соответствует бренду #43 в капсуле владельца.»
  • Нельзя передавать между задачами:Токены — это «доказательства прав доступа на этапе компиляции», их нельзя перемещать между потоками. Если нужна передача между задачами, используйте ref. Почему? Потому что компилятор сказал нельзя. Фактически — потому что токены исчезают после компиляции: тип нулевого размера, нулевые накладные расходы в runtime, но и нулевая возможность межзадачной передачи.

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

3.5 Инновация пятая: 并作-модель —— Самая ужасная часть языка

«Все существа действуют, и я наблюдаю их возвращение.»——《И·Фу-гуа》

Главное преимущество 并作-модели:синхронный синтаксис, асинхронная суть. Переведём на человеческий: ваш код выглядит выполняющимся последовательно, но в runtime автоматически распараллеливается. Когда распараллелить? Как распараллелить? Решает компилятор. Это не модель конкурентности, это игра на доверие.

Давайте посмотрим, что мы впихнули в язык ради этого волшебства:

Ключевое слово 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) можно использовать в сигнатуре типа. Хотя это не имеет никакого отношения к написанию бизнес-логики, «типы — это утверждения, программы — это доказательства» — круто, да?

Не забудьте про decreases-контракт: все рекурсивные функции, вычисляемые при компиляции, должны доказать, что они завершатся. Иначе ваш проверяльщик типов уйдёт в бесконечный цикл, а ваша IDE превратится в обогреватель. «Извините, вашей функции factorial не хватает decreases-контракта. Компилятор не знает, остановится ли она при n=-1 или будет рекурсировать до тепловой смерти вселенной.»

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
# === 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 = sharing. Компилятор автоматически выбирает Rc. Или Arc. Вам знать не положено.
backup = p2.clone()  # Глубокое копирование. Почему не ref? Потому что ref — это не копирование, а sharing. Понятно?

# === Унифицированный синтаксис: name: type = value ===
# Можете ли вы определить, что из нижеследующего является типом, функцией или переменной?
# Ответ: никак. В этом и есть «красота унификации».
identity: (T: Type) -> ((x: T) -> T) = x
List: (T: Type) -> Type = { data: Array(T), length: Int }

# === Типы, зависящие от значений: факториал в сигнатуре типа ===
factorial: (n: Int) -> Int = {
    # decreases: n  ← без этого компилятор будет паниковать
    if n <= 1 { return 1 }
    return n * factorial(n - 1)
}
vec: Vec(factorial(5)) = Vec(120)()  # Тип Vec(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

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


五、Дорожная карта и открытые вопросы —— Список желаний

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

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

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

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

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

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

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

5.2 Открытые для обсуждения темы

Включают «литеральный синтаксис», «выведение generics», «pattern matching» и другие мелочи. Ключевая философия уже совершенна, эти пустяки можно обсудить потом.

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

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

5.4 Текущий статус реализации

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

六、Как участвовать —— Пожалуйста, возьмите с собой время, энтузиазм и сниженные ожидания

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

6.1 Дизайнерские обсуждения

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

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

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

Сейчас больше всего нужны:

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

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

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

6.4 Развитие стандартной библиотеки

От std.io до std.gui, всё должно быть. Что есть сейчас: std.placeholder. Следующий шаг: std.placeholder_v2.

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

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

6.7 Руководство по вкладу

Формат сообщений коммитов: должен быть стих. Предпочтительно сонет. Хаiku тоже приемлемо:

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

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

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

Q: Для чего подходит YaoXiang?
A: Подходит для разработки компилятора YaoXiang. А также для написания дизайн-манифестов и RFC. Другие варианты использования有待研究.

Q: Почему выбран 4-пробельный отступ?
A: 2 пробела слишком тесно, 8 пробелов слишком просторно, 4 пробела — это путь середины, соответствующий духу «И Цзин».

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

Q: Почему 14 принятых RFC, но версия всё ещё 0.7.0?
A: Потому что мы играем в большую игру. Дизайн впереди, реализация позже. Очень позже.

Q: ref — это Rc или Arc?
A: Компилятор выбирает автоматически. Вам не нужно об этом думать. Фактически, это единственный момент, когда компилятор разбирается лучше пользователя, поэтому мы даём полномочия.

Q: Когда 并作-модель реально заработает?
A: Когда вы читаете эту строку, ответ всё ещё: «стадия дизайна, не реализовано». Но ключевое слово spawn уже правильно парсится, разве это не захватывает?

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

Q: Как связаться с core team?
A: Напишите в GitHub Discussions. Время ответа: 1-3 рабочих месяца.


七、Больше красивых историй

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

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

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

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

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

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

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


«爻象变化,万物生焉。类型演化,程序成焉。」

Пусть путешествие дизайна YaoXiang станет увлекательной темой для разговоров за чаем и после еды.
(В конце концов, на данном этапе это в основном и есть тема для разговоров.)