AnyCompiler

Option e Result

Rust não tem null. Um valor que pode estar ausente é envolvido em Option<T>, que é Some(value) ou None — e o compilador força você a tratar os dois casos antes de poder usar o valor interno, então um valor ausente nunca pode ser usado acidentalmente como se estivesse presente.

fn find_first_even(numbers: &[i32]) -> Option<i32> {
    for &n in numbers {
        if n % 2 == 0 {
            return Some(n);
        }
    }
    None
}

fn main() {
    let numbers = vec![1, 3, 5, 4, 7];
    match find_first_even(&numbers) {
        Some(n) => println!("Found: {}", n),
        None => println!("No even number found"),
    }
}
Output
Found: 4

Result para erros recuperáveis

Result<T, E> representa uma operação que pode falhar: Ok(value) em caso de sucesso, Err(error) em caso de falha. Não há exceções para lançar ou capturar aqui — uma função que pode falhar simplesmente retorna um Result, e match obriga quem a chama a tratar ambos os resultados explicitamente.

fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err(String::from("cannot divide by zero"))
    } else {
        Ok(a / b)
    }
}

fn main() {
    match divide(10.0, 2.0) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }

    match divide(10.0, 0.0) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }
}
Output
Result: 5
Error: cannot divide by zero

Próximo: funções — parâmetros, tipos de retorno, e a sintaxe baseada em expressões do Rust.

Practice Exercise

Escreva uma função first_char(s: &str) -> Option<char> que retorne o primeiro caractere de s, ou None se s estiver vazio. Chame-a com "rust" e faça match do resultado, imprimindo o caractere se for Some, ou "empty" se for None.