Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Controle de Fluxo Let

Rust possui algumas construções de fluxo de controle que diferem de outras linguagens. Elas são usadas para correspondência de padrões:

  • Expressões if let
  • Expressões let else
  • Expressões while let

Expressões if let

A expressão if let lhe permite executar um código diferente caso um valor corresponde a um padrão:

use std::time::Duration;

fn sleep_for(secs: f32) {
    if let Ok(dur) = Duration::try_from_secs_f32(secs) {
        std::thread::sleep(dur);
        println!("dormiu por {:?}", dur);
    }
}

fn main() {
    sleep_for(-10.0);
    sleep_for(0.8);
}

Expressões let else

Para o caso comum de corresponder a um padrão e retornar da função, use let else. O caso “else” deve divergir (return, break ou pânico - qualquer coisa, exceto cair no final do bloco).

fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> {
    let s = if let Some(s) = maybe_string {
        s
    } else {
        return Err(String::from("obteve None"));
    };

    let first_byte_char = if let Some(first_byte_char) = s.chars().next() {
        first_byte_char
    } else {
        return Err(String::from("obteve uma string vazia"));
    };

    if let Some(digit) = first_byte_char.to_digit(16) {
        Ok(digit)
    } else {
        Err(String::from("não é um dígito hexadecimal"))
    }
}

fn main() {
    println!("result: {:?}", hex_or_die_trying(Some(String::from("foo"))));
}

Similar a if let, há uma variante while let que testa repetidamente se um valor corresponde a um padrão:

fn main() {
    let mut name = String::from("Comprehensive Rust 🦀");
    while let Some(c) = name.pop() {
        println!("character: {c}");
    }
    // (There are more efficient ways to reverse a string!)
}

Aqui String::pop retorna Some(c) até que a string esteja vazia e depois ela retornará None. O while let nos permite iterar por todos os itens.

This slide should take about 10 minutes.

if-let

  • Ao contrário de match, if let não precisa cobrir todas as ramificações. Isso pode torná-lo mais conciso do que match.
  • Um uso comum é lidar com valores Some ao trabalhar-se com Option.
  • Ao contrário de match, if let não suporta cláusulas de guarda para correspondência de padrões.

let-else

if-lets podem se acumular, como mostrado. A construção let-else permite o “achatamento” desse código aninhado. Reescreva a versão “estranha” para os alunos, para que eles possam ver a transformação.

A versão reescrita é:

#![allow(unused)]
fn main() {
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> {
    let Some(s) = maybe_string else {
        return Err(String::from("obteve None"));
    };

    let Some(first_byte_char) = s.chars().next() else {
        return Err(String::from("obteve uma string vazia"));
    };

    let Some(digit) = first_byte_char.to_digit(16) else {
        return Err(String::from("não é um dígito hexadecimal"));
    };

    return Ok(digit);
}
}

while-let

  • Ressalte que o loop while let continuará executando enquanto o valor corresponder ao padrão.
  • Você pode reescrever o loop while let como um loop infinito com uma instrução if que é interrompido quando não houver mais nenhum valor para unwrap (desempacotar) para name.pop(). O while let fornece um atalho para o cenário acima.