Saltar al contenido

El operador ?

En esta página

El operador ? es azúcar sintáctico para la propagación automática: si el valor es Result::Ok(v), extrae v; si es Result::Err(e), retorna el error inmediatamente al llamador. El efecto es el mismo que match + return, pero sin el ruido visual.

El archivo a continuación compara la forma verbosa con la concisa y muestra que ? también funciona con T? (opcional):

? en Result y en Option: propagación limpia sin if/match manuales.

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

La función que usa ? debe tener un tipo de retorno compatible: Result<_, E> para Result, o T? para opcionales.

Desafío

Intenta llamar compute(100, 4, 0) y compute(0, 1, 1). ¿Qué paso de la cadena dispara el error en cada caso? Cambia divide para retornar 0 en lugar de Err cuando b == 0 y observa qué cambia.

Buscar en Zolo

9 resultados

enespt-br