← Все решения

Philosophy — цели, парадигма, AI-first

Решения этой группы задают рамку всех остальных: зачем нужна Nova, на какой комбинации идей она строится, чем оптимизируется. Конкретные правила синтаксиса и семантики — в других файлах spec/decisions/.

#Решение
D1Парадигма: protocols + data, без классов
D9Честная оценка новизны
D10Революционная ставка: «всё — эффект» + AI-first

D1. Парадигма: protocols + data, без классов

Что

Nova — язык без классов и наследования. Данные и поведение разделены: record-типы хранят данные, методы привязаны к типу через @-синтаксис, структурные protocol-контракты задают «роли», use-делегация заменяет наследование.

Правило

Четыре строительных блока, и только они:

// 1) Данные — record, sum-type, alias
type Account {
    readonly owner str
    balance money
}

// 2) Static-функции и конструкторы
fn Account.new(owner str) -> Account =>
    Account { owner, balance: money.zero }

// 3) Методы инстанса через @
fn Account @balance() => @balance
fn Account mut @deposit(amount money) {
    @balance += amount
}

// 4) Структурный контракт через protocol
type Hashable protocol {
    hash() -> u64
    eq(other Self) -> bool
}

Замена наследования — use name Type внутри type (alias обязателен, D39):

type AuditedAccount {
    use account Account             // delegation, не наследование
    audit_log []AuditEntry
}

Компилятор генерирует прокси-методы; AuditedAccount не подтип Account. Подробно — 02-types.md → D39.

Почему

  1. Наследование — известный антипаттерн. Fragile base class, diamond problem, божественные классы. Go доказал, что без классов можно жить; Rust — что без GC и наследования можно писать сложные системы; OCaml — что sum-types убивают половину паттернов GoF.
  2. Структурно, а не номинально. Любой тип со совпадающими методами автоматически удовлетворяет protocol-контракту. Никаких impl Trait for Type-блоков (как в Rust).
  3. Локальность чтения. Метод привязан к типу через fn Type @method, виден рядом с типом, не размазан по impl-блокам.

Что отвергнуто

  • Классы и наследование. Антипаттерн, см. выше.
  • trait + impl Trait for Type (Rust-стиль). Заменено на структурный protocol (D9, D42) — без impl-блоков.
  • mut self как параметр. Заменено на fn Type mut @method() — модификатор перед @. См. 03-syntax.md → D35.

Связь

Эволюция

В ранних черновиках использовались Rust-style trait / impl Trait for Type. Отказались в пользу структурного protocol (D42) — без явного impl-блока, по совпадению методов. Старая модель (trait/impl) ещё описана в paradigm.md, файл помечен устаревшим до полной переписи. См. history/evolution.md.


D9. Честная оценка новизны

Что

Nova не изобретает ни одной фичи в одиночку — каждая идея уже где-то есть. Заявка на новизну — сочетание идей в одном прикладном языке. Это слабая заявка, которую нужно держать честно перед глазами, чтобы дизайн не превращался в «всего понемногу».

Откуда взяты идеи

ИдеяИсточник
Effect systemKoka, Effekt, Eff
Регионы памятиZig, Odin, Cyclone
protocol + sum-typesSwift, Rust, OCaml
Структурная типизацияGo, TypeScript
Три режима компиляцииJulia
Embed-delegationGo
Мономорфизация + dynRust
Fiber runtimeGo, OCaml 5, Erlang
Контракты (requires/ensures)Eiffel, Spec#, Dafny

Почему «языки-комбинаторы» проваливаются

Scala, D, Nim, Crystal — все технически сильные, ни один не доминирует. Языки выигрывают не фичами, а экосистемой + killer use-case:

  • Go — серверы (Google + Docker/Kubernetes).
  • Rust — системное (Mozilla + Linux kernel).
  • Python — ML (NumPy / PyTorch).
  • TypeScript — фронт (Microsoft + VS Code).

У гипотетической Nova ни одного из этих рычагов нет.

Две вещи, которые могли бы быть реально новыми

Если выбирать одно предложение на вопрос «зачем переходить с того, что есть» — это:

1. Effect system в прикладном языке с понятными ошибками. Koka/Effekt/Eff — академические, на них никто не пишет в продакшне. Нет ни одного прикладного языка, где effects заменили async/throws/unsafe одновременно и были бы понятны программисту с Java-фоном за день. Решающая инженерная задача — сообщения компилятора про эффекты. В Koka они академически точны и человечески непонятны. Никто пока эту задачу не решил.

2. Три режима компиляции (AOT/JIT/интерпретатор) в строго типизированном языке без жертв. Julia умеет JIT+AOT, но типизация слабая. C# умеет AOT+JIT, но REPL ограниченный. Go умеет AOT, REPL нет. TypeScript = только интерпретация. Nova могла бы быть первым строго типизированным языком, где nova run script.nv работает как Python, а nova build даёт бинарь как Go — без переписывания.

Что не является заявкой

protocols + data, регионы памяти, structured concurrency, sum-types — это повторение лучших практик. Нужно, чтобы язык вообще был хорошим, но не отличает Nova от Rust/Swift/Kotlin. Заявлять «у нас sum-types» в 2026 — как заявлять «у нас замыкания» в 2010. Базовый санитар.

Главный вывод для дизайна

Если очередная идея не усиливает одну из двух уникальных заявок выше, а просто «делает язык хорошим» — её добавлять можно, но не надо выдавать за отличие. И до написания компилятора нужно ответить письменно: «зачем мне переходить с X на Nova одним предложением». Большинство языков-неудачников начали с компилятора, а не с этого вопроса.

Связь


D10. Революционная ставка: «всё — эффект» + AI-first

Что

Nova переходит от «хорошего языка с набором фич» к языку с одной центральной абстракцией и одним killer use-case. Центральная абстракция — алгебраические эффекты. Killer use-case — AI-first язык, оптимизированный под пару «LLM пишет, человек ревьюит».

Центральная абстракция: всё — эффект

Не просто Fail/Io. Любое взаимодействие с внешним миром — эффект: аллокация в region (Alloc[R]), время (Time), случайность (Random), сеть (Net), БД (Db), файлы (Fs), лог (Log), и пользовательские эффекты, которые программист объявляет сам через effect keyword (D61). Эффекты алгебраичны (Koka/Effekt-style): у каждого есть handler — функция, перехватывающая эффект и решающая, что с ним делать.

(Suspension и параллелизм — runtime-инфраструктура, не эффекты; см. D62, D14, D50. Изменяемое состояние — через mut поля и параметры, не эффект Mut.)

Из этой одной идеи следует всё:

  • Тестирование без моков = подмена handler’а.
  • Транзакции = handler эффекта Db.
  • Undo/redo = handler специализированного state-эффекта (Counter, History — каждый со своим именем; generic Mut удалён в D62).
  • Детерминированный запуск = handler Time + Random с фиксированными значениями.
  • Трассировка = handler-обёртка над любым эффектом.
  • Capability security = разрешённые handler’ы в скоупе.

Подробно — 04-effects.md.

Killer use-case: AI-first язык

LLM пишет 50–80% кода в 2026+. Все существующие языки спроектированы до этой эпохи, под человека. Nova явно оптимизирует под пару «LLM пишет, человек ревьюит»:

  • Локальность контекста — функция понятна без 10 файлов вокруг (нет неявных импортов, нет DI через рефлексию, нет хуков-невидимок).
  • Сигнатура = полное описание поведения — типы + эффекты + pre/postconditions, читая сигнатуру знаешь всё.
  • Ошибки компилятора как обучающий сигнал — формат, по которому LLM фиксит код за одну итерацию, без человека-посредника.
  • Стабильность синтаксиса — никаких революций каждые 2 года, LLM учится на старых данных.
  • Проверяемость по фрагменту — типечекинг одной функции без всего проекта.
  • Эффекты делают код безопасным для AI-генерации — невозможно «случайно» сходить в сеть/БД, это видно в сигнатуре.

Почему это связано в одно

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

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

  • «Хороший язык в духе Swift/Kotlin» как цель — заменено на конкретную ставку.
  • «Всего понемногу» (Go + Rust + OCaml + Julia) — теперь Nova следует из одной идеи, а не комбинирует пять.
  • Effects как «ещё одна фича рядом с traits» — теперь это центр.

Что остаётся

  • protocols + data (D1) — следствие «всё эффект»: метод протокола может иметь эффект.
  • Managed memory (05-memory.md → D6) — программист пишет без префиксов памяти. Real-time зоны через эффект Realtime (тело оборачивается в region автоматически).
  • Три режима компиляции (08-runtime.md → D7) — handler’ы перехватываются и в JIT, и в AOT, и в интерпретаторе одинаково.
  • Структурная типизация — без изменений (D9 / D42).

Что добавляется

  • Handler-блоки — синтаксис подмены эффектов (with Effect = handler { ... }).
  • Capability-режим — функция декларирует, какие эффекты разрешены в её скоупе (forbid Net, Fs { body }).
  • Контрактыrequires/ensures/invariant как часть сигнатуры (09-tooling.md → D24).
  • Детерминированный режим тестирования — встроенный handler-стек, фиксирующий время/случайность/IO.

Цена и риски

  1. Effect system сложнее в реализации. Алгебраические эффекты с handler’ами — нетривиальный compilation target. Koka и Effekt академические, не показывают production-grade перформанс.
  2. AI-first как позиционирование требует, чтобы Nova стабильно выдавала качественный LLM-код уже в v0.1. Это означает упор на стабильность синтаксиса и качество ошибок с самого начала.
  3. Узкая ставка — если AI-first не «выстрелит», Nova остаётся ещё одним «языком-комбинатором» (см. D9).

Связь

Эволюция

D10 пересматривает раннюю позицию «хороший язык в духе Swift/Kotlin». Подробно — history/evolution.md.