Pular para o conteúdo principal
Módulo 2 · Lição 2 de 24/14 no curso~15 min
Lições do módulo (2/2)

Correspondência de padrões, opção e resultado

Rust tem um mecanismo de fluxo de controle extremamente poderoso chamado correspondência de padrões. Ele permite comparar um valor com uma série de padrões e executar código com base no padrão correspondente.

A Declaração match

A instrução match em Rust é semelhante a switch em outras linguagens, mas muito mais poderosa e segura. O compilador garante que a correspondência seja exaustiva, o que significa que todos os casos possíveis devem ser tratados:

Rust
enum Direction {
    North,
    South,
    East,
    West,
}

let dir = Direction::East;

match dir {
    Direction::North => println!("Andiamo a Nord"),
    Direction::South => println!("Andiamo a Sud"),
    Direction::East => println!("Andiamo a Est"),
    Direction::West => println!("Andiamo a Ovest"),
}

Lidando com ausência de valor: Option

Rust não possui o conceito de valor nulo (null ou nil). Em vez disso, a biblioteca padrão define uma enumeração chamada Option<T> que pode conter:

  • Some(T): contém um valor do tipo T.
  • None: indica ausência de valor.
Rust
let x: Option<i32> = Some(5);
let y: Option<i32> = None;

match x {
    Some(val) => println!("C'e un valore: {}", val),
    None => println!("Nessun valore trovato"),
}

Tratamento de erros recuperáveis: Result

Para operações que podem falhar (como ler um arquivo ou analisar uma string em um número), Rust usa o enum Result<T, E>, que tem duas variantes:

  • Ok(T): a operação foi bem-sucedida e contém o valor de sucesso T.
  • Err(E): a operação falhou e contém o erro E.
Rust
fn divide(numerator: f64, denominator: f64) -> Result<f64, String> {
    if denominator == 0.0 {
        Err(String::from("Divisione per zero!"))
    } else {
        Ok(numerator / denominator)
    }
}

Graças ao compilador Rust, você é forçado a lidar com o caso Err antes de poder acessar o valor dentro de Ok, evitando muitos bugs comuns de tempo de execução.

O padrão curinga _

Ao trabalhar com tipos de dados que possuem um grande número de variantes (como números inteiros), é impossível listar todos os casos em um match. Rust permite usar o caractere curinga _ para capturar todos os casos restantes não definidos explicitamente:

Rust
let some_u8 = 3u8;
match some_u8 {
    1 => println!("One"),
    2 => println!("Two"),
    _ => println!("Something else"), // Handles all other values
}

Experimente você mesmo

Exercício#rust.m2.l2.e1
Tentativas: 0Carregando…

Declare uma variável chamada talvez_valor do tipo Option<i32> contendo Some(42). Use uma instrução de correspondência em talvez_valor: se contiver Some(v) imprima 'valor é: v' (usando println!), se contiver None imprima 'nenhum valor'.

Carregando editor…
Mostrar dica

Escreva um bloco `match Maybe_value { Some(v) => println!('value is: {}', v), None => println!('no value') }`.

Solução disponível após 3 tentativas

Exercício#rust.m2.l2.e2
Tentativas: 0Carregando…

Complete a função check_age para que ela retorne Ok('Adult') se a idade for maior ou igual a 18, e Err('Minor') caso contrário.

Carregando editor…
Mostrar dica

Use `if age >= 18` para decidir se deseja retornar`Ok('Adulto')`ou`Err('Menor')`.

Solução disponível após 3 tentativas

Exercício#rust.m2.l2.e3
Tentativas: 0Carregando…

Declare uma enumeração chamada Status contendo as variantes Ativa e Inativa. Em main, declare uma variável current_status com o valor Status::Active. Finalmente, use uma instrução match em current_status para imprimir 'ativo' se o status for Ativo ou 'inativo' se o status for Inativo.

Carregando editor…
Mostrar dica

Defina o enum antes de main com `enum Status {Active, Inactive}`. Em main, use `let current_status = Status::Active;`e execute o`match` nas variantes.

Solução disponível após 3 tentativas