Pular para o conteúdo

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
Playground
// 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> para Result, ou T? 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.

Buscar no Zolo

9 resultados

enespt-br