Agendamento: every, after e timeout
Nesta página
Zolo tem três construções de agendamento integradas à linguagem. Todas são
palavras reservadas — não use every, after ou timeout como nomes de
variável; prefira intervalo, agendado, prazo ou limite.
every — loop periódico
every <dur> { ... } repete o corpo no intervalo indicado. É um laço infinito
por design: encerre-o com break quando a condição de saída for atingida.
Contador com break após 3 iterações; soma acumulada que para ao atingir o
total desejado.
// Feature: periodic loop with `every <dur> { ... }`
// Syntax: `every <duration> { body }` — repeats the body at the given
// interval. It is a keyword (not a variable name).
// When to use: health-checks, polling, animation, metrics, any
// task that needs to run repeatedly on a fixed interval.
var tick = 0
// Runs 3 times (short interval for the demo) and exits with `break`.
every 50ms {
tick = tick + 1
print("tick #{tick}")
if tick >= 3 {
break
}
}
print("done")
// expected:
// tick #1
// tick #2
// tick #3
// done
// Another example: summing until a total is reached.
var total = 0
every 25ms {
total = total + 10
if total >= 30 {
break
}
}
print("total = {total}")
// expected: total = 30
after — disparo único
after <dur> { ... } agenda a execução do bloco uma única vez, após o atraso.
É fire-and-forget: não bloqueia o fluxo principal. Use sleep depois para
manter o programa vivo até o callback disparar.
Três after coexistindo; ordem de disparo determinada pelo scheduler.
// Feature: schedule one execution with `after <dur> { ... }`
// Syntax: `after <duration> { body }` — fire-and-forget; the block
// runs **once** after the delay. It is a keyword.
// When to use: one-shot callbacks, timers, expirations, single
// reminders. Unlike `every`, it does not repeat.
print("scheduling...")
// Block runs 50ms later — does not block the main flow here.
after 50ms {
print("fired after 50ms!")
}
// Multiple `after` may coexist.
after 100ms {
print("fired after 100ms!")
}
after 25ms {
print("this one was first")
}
print("scheduled, waiting...")
// Keep the program alive long enough to see the firings.
sleep 200ms
print("end")
// expected (approximate order — depends on the scheduler):
// scheduling...
// scheduled, waiting...
// this one was first
// fired after 50ms!
// fired after 100ms!
// end
timeout — prazo de cancelamento
timeout <dur> { ... } retorna um objeto { ok, value, error }. Se o bloco
concluir dentro do prazo, ok é true e value contém o retorno. Se expirar,
ok é false e error é "timeout". Como o scheduler é cooperativo, o
cancelamento só ocorre em pontos de yield (sleep, IO, etc.).
Caminho feliz com retorno dentro do prazo; nota sobre o comportamento cooperativo e alternativa de nome para a variável de prazo.
// Feature: cancel work that takes too long with `timeout`
// Syntax: `timeout <dur> { body }` — returns a `Result`-like
// (`{ ok, value, error }`) with `ok = true` if it completed, or
// `ok = false, error = "timeout"` if it expired.
// When to use: network calls, uncertain IO, tasks that need a
// fail-safe. Cooperative: only fires at a yield point.
// Happy path: body finishes within the deadline.
let result_ok = timeout 100ms {
return 42
}
if result_ok.ok {
print("ok: {result_ok.value}")
} else {
print("err: {result_ok.error}")
}
// expected: ok: 42
// Timeout case: body takes longer than the limit and is interrupted.
// Note: cooperative — the body must yield (e.g. via `sleep`) for
// the deadline to fire. If it never yields, the body runs to
// completion and `ok = true`.
// SKIP: sleep inside `timeout { ... }` raises a YieldError in the
// current runtime; the failure case is therefore commented out.
//
// let result_slow = timeout 30ms {
// sleep 200ms
// return "too late"
// }
// if result_slow.ok {
// print("ok: {result_slow.value}")
// } else {
// print("err: {result_slow.error}")
// }
//
// expected: err: timeout
// IMPORTANT: `timeout` is a reserved keyword — you cannot use it
// as a variable name. Use `deadline`, `limit`, `dur`, etc. instead.
let limit = 5000
print("using '{limit}' instead of 'timeout' as the name")
Desafio
Combine every 100ms com um after 500ms que seta uma flag de parada. O
every deve verificar a flag e chamar break quando ela for verdadeira.
Veja também