Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Вычисления и вывод: = против :

Главное правило Aura, отличающее её от YAML/JSON (аналог locals vs outputs в Terraform):

ФормаСмыслВ выводе?
x = exprприватная переменнаянет
key: exprсвойствода
domain "name" ... endблокда (ключ = имя)
base = 8000     # вычисление
port: base + 80 # вывод: {"port": 8080}

Благодаря этому анализ мёртвого кода точен: неиспользуемая =-переменная — всегда настоящий мусор (W0501), а не «может, это чей-то вывод».

Иммутабельность

Повторное присваивание в одной области — ошибка:

x = 1
x = 2 # E0301: variable 'x' is immutable

Явное затенение

Переопределить внешнюю переменную во вложенном блоке можно только явно:

log_path = "/var/log/app.log"

domain "debug"
  log_path        = "/tmp/debug.log" # E0302: требуется shadow
  shadow log_path = "/tmp/debug.log" # ок — намерение видно в diff'е
  path: log_path                     # → "/tmp/debug.log"
end

«Почему в проде другой путь?» больше не тихий сюрприз — затенение всегда видно по слову shadow.

Длинные числа

Разделяйте разряды через _ там, где это помогает глазу:

max_bytes: 10_000_000
retention: 2_592_000
port:      8_080
rate:      0.000_001 # в дробной части группы отсчитываются от точки

Это полностью необязательно: 2371933 и 2_371_933 — одно и то же число, и никто не требует что-либо группировать.

Но если вы группируете, разделитель обязан разбивать по три, считая от десятичной точки. Поэтому короткая группа оказывается в начале целой части и в конце дробной: 8_080, 1.123_45.

Это строже, чем в Go, Ruby или Rust, где 2_3_7_1_9_3_3 допустимо. Причины две. Разделитель, который может стоять где угодно, — это второй способ записать одно и то же число, а язык тратит свои правила ровно на то, чтобы таких способов не было. И он вводит в заблуждение: 1_0000_000 — это десять миллионов, но всякий, кто читает по три, увидит куда большее число.

100_, 1__0 и 1_.5 — тоже ошибки: разделять там нечего.

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

Строки и интерполяция

name = "auth"
image: "company/#{name}:v#{1 + 1}" # → "company/auth:v2"

Внутри #{...} — обычный синтаксис выражений: кавычки вложенных строк не экранируются ("#{list.join(", ")}" — валидно).

У null нет текстовой формы, поэтому его интерполяция — это E0324, а не слово null:

host = env("HOST", null)
url: "https://#{host == null ? "localhost" : host}/api"

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

Доступ к данным

Точка — для полей, скобки — только для индексов списков:

version:  cfg.package.version         # обычные ключи
special:  cfg."ключ с пробелом"       # любой ключ — строкой
dynamic:  cfg.envs."#{region}"        # динамический ключ
first:    apps[0].name                # индекс (за границами — E0317)
optional: cfg.get("maybe", "default") # промах → default, не ошибка

Опечатка в имени поля — ошибка E0308 с точной позицией, а не молчаливый null.