Параллельная работа явно выражается concurrent; язык фиксирует форму результата, timeout fallback, fault propagation и совместимость типов без неявной async-модели.
Политика
concurrent { named: expression } — простой join. Для public-docs основной вид: concurrent(timeout: 3s) { ... } else { fallback }. Именованные arms вычисляются параллельно, а успешный результат — record с полем каждого arm. Fallback запускается только при истечении deadline, обязан быть совместим с record и не получает частичный результат.
Определённое поведение
Fault arm до timeout завершает fault всего выражения и не выбирает else. Err остаётся обычным значением arm. Abandoned work и cancellation после timeout — runtime policy; поздние faults не наблюдаются выражением. Duration literal — соседние integer и ms, s либо m, только в timeout clause. Имена arms уникальны и становятся полями результата.
Ограничения и явный отказ
Join не принимает else, timeout form не может его опустить. Отклоняются 3 s, property duration вроде .seconds, повторные arms, несовместимый fallback, partial-result access и утверждение, что else обрабатывает failure. Язык не обещает порядок запуска/завершения arms или deterministic interleaving.
Отложенная граница
async, await, automatic async I/O, futures, user task handles, cancellation semantics, общая duration arithmetic, fairness планировщика, deterministic interleaving и portable cleanup abandoned tasks находятся вне языка. Toolchain может описывать измеренное поведение, не превращая его в семантику.
Пример
function loadUser(id: int) -> Option<string> { Some("Ada") }
function loadPosts(id: int) -> Array<string> { ["first", "second"] }
let dashboard = concurrent(timeout: 3s) {
user: loadUser(7)
posts: loadPosts(7)
} else {
{ user: None, posts: [] }
}