Operador ?
Nesta página
O operador ? é açúcar sintático para propagação automática: se o valor for
Result::Ok(v), ele extrai v; se for Result::Err(e), retorna o erro
imediatamente para quem chamou. O efeito é o mesmo de um match + return,
mas sem o ruído visual.
O arquivo abaixo compara a forma verbosa com a forma concisa e mostra que ?
também funciona com T? (opcional):
? em Result e em Option: propagação limpa sem if/match manuais.
03-try-operator.zolo
// Feature: `?` operator — automatic propagation
// Syntax: `let x = expr?` (extracts Ok or returns Err)
// When to use: chain Result-returning calls without boilerplate.
use std::Result
fn divide(a: int, b: int) -> Result<int, str> {
if b == 0 {
return Result.Err("division by zero")
}
return Result.Ok(a / b)
}
// Without `?` — nested match, verbose:
fn compute_verbose(a: int, b: int, c: int) -> Result<int, str> {
let r1 = divide(a, b)
if r1.is_err() {
return r1
}
let x = r1.unwrap()
let r2 = divide(x, c)
if r2.is_err() {
return r2
}
return Result.Ok(r2.unwrap())
}
// With `?` — clean:
fn compute(a: int, b: int, c: int) -> Result<int, str> {
let x = divide(a, b)? // if Err, returns Err immediately
let y = divide(x, c)? // same here
return Result.Ok(y)
}
fn describe(r: Result<int, str>) {
match r {
Result::Ok(v) => print("ok: {v}"),
Result::Err(e) => print("error: {e}"),
}
}
describe(compute(100, 4, 5))
// expected: ok: 5
describe(compute(100, 0, 5))
// expected: error: division by zero
describe(compute(100, 4, 0))
// expected: error: division by zero
// Verbose and short forms produce the same result:
describe(compute_verbose(100, 4, 5)) // ok: 5
describe(compute_verbose(100, 0, 5)) // error: division by zero
// `?` also works with Option (T?). If None/nil, returns nil.
fn first(arr: [int]) -> int? {
if arr.len() == 0 {
return nil
}
return arr[0]
}
fn sum_firsts(a: [int], b: [int]) -> int? {
let x = first(a)?
let y = first(b)?
return x + y
}
print(sum_firsts([1, 2], [3, 4])) // 4
print(sum_firsts([], [3, 4])) // nil
print(sum_firsts([1], [])) // nil
A função que usa
?deve ter tipo de retorno compatível:Result<_, E>paraResult, ouT?para opcionais.
Desafio
Experimente chamar compute(100, 4, 0) e compute(0, 1, 1). Qual passo da
cadeia dispara o erro em cada caso? Altere divide para retornar 0 em vez
de Err quando b == 0 e observe o que muda.