OxL Справочник OxL
РусскийEnglish

Шаг 8. Эффекты

Зачем#

Если функция называется total(items), мы ожидаем, что она посчитает сумму. Но может ли она заодно сходить в сеть, прочитать файл или уснуть на секунду? В большинстве языков это нельзя узнать, не прочитав тело. В OxL это видно в сигнатуре:

ЭффектРазрешает
ioфайлы, процессы, окружение, stdout/stderr
netсеть: rpc, HTTP, акторы, кластер
dbORM, std.kv, встроенное хранилище
timeчтение часов, sleep, таймеры
randслучайные числа
pureничего из перечисленного

Функция может вызывать только функции, чьи эффекты входят в её собственный набор. Поэтому pure-функции легко тестировать (результат зависит только от аргументов), а подозрительные места — где что-то «просачивается» — находит компилятор. Те же эффекты говорят планировщику, что функцию можно приостановить, поэтому в OxL нет async/await и «цвета» функций.

Пример#

oxl✓ проверяется в CI
fn double(x: i32) -> i32  pure => x * 2  // pure: нет ни ввода-вывода, ни времени

fn log(msg: str) io {  // io: пишет в stdout
  print("[log] {msg}")
}

fn timed(x: i32) -> i32  io, time {  // несколько эффектов через запятую
  log("sleeping")
  sleep(5ms)
  double(x)  // pure-функцию можно вызывать откуда угодно
}

fn main() io, time {
  print("{timed(21)}")
}
Вывод
[log] sleeping
42

Разбор#

  • double — pure: вызывается откуда угодно, включая другие pure-функции.
  • log объявляет io (в -> () форме тип результата опускается).
  • timed перечисляет io, time: внутри она вызывает и log, и sleep. main тоже обязан объявить io, time.
  • У приватных функций эффекты можно не писать — компилятор выведет их. У pub(api) функций эффекты обязательны: это часть публичного API, и изменение эффектов — ломающее изменение.
  • Паника эффектом не считается: она возможна в любой функции.

Типичная ошибка: эффект не объявлен#

oxl✓ проверяется в CI
fn calc() -> i32  pure {
  sleep(1s)  // sleep требует эффекта time
  42
}
error
effects

effects: calc объявлена pure, но вызывает sleep, а ему нужен time. Исправить можно двумя способами: добавить эффект в сигнатуру (-> i32 time) и объявить его у всех вызывающих — или убрать sleep из функции, которая должна оставаться чистой. Второй способ обычно лучше: держите бизнес-логику pure, а ввод-вывод — на краях программы.

Что запомнить#

  • Эффекты — часть типа функции; pure — отсутствие эффектов.
  • Вызывающий должен «позволять» все эффекты вызываемого.
  • Чистое ядро + тонкая оболочка с эффектами — естественная архитектура на OxL.

Дальше: модули и пакеты.

См. также

OxL 1.0.0-beta · Версия документации 1.0.0-beta© OxwaldLink · сгенерировано из Стандарта, исходников std и руководства