Funções Divergentes em Rust

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Neste laboratório, aprendemos sobre funções divergentes marcadas com ! em Rust. Funções divergentes nunca retornam e seu tipo de retorno é um tipo vazio. Isso difere do tipo () que possui apenas um valor possível. Funções divergentes podem ser úteis quando é necessário fazer casting para qualquer outro tipo, como em ramos match. Elas também são o tipo de retorno de funções que loopam para sempre ou terminam o processo.

Nota: Se o laboratório não especificar um nome de arquivo, você pode usar qualquer nome de arquivo que desejar. Por exemplo, você pode usar main.rs, compilar e executar com rustc main.rs && ./main.

Funções Divergentes

Funções divergentes nunca retornam. São marcadas usando !, que é um tipo vazio.

fn foo() -> ! {
    panic!("Esta chamada nunca retorna.");
}

Ao contrário de todos os outros tipos, este não pode ser instanciado, porque o conjunto de todos os valores possíveis que este tipo pode ter é vazio. Note que é diferente do tipo (), que tem exatamente um valor possível.

Por exemplo, esta função retorna normalmente, embora não haja informação no valor de retorno.

fn some_fn() {
    ()
}

fn main() {
    let _a: () = some_fn();
    println!("Esta função retorna e você pode ver esta linha.");
}

Ao contrário desta função, que nunca retornará o controle de volta para o chamador.

#![feature(never_type)]

fn main() {
    let x: ! = panic!("Esta chamada nunca retorna.");
    println!("Você nunca verá esta linha!");
}

Embora isso possa parecer um conceito abstrato, na verdade é muito útil e frequentemente prático. A principal vantagem deste tipo é que ele pode ser convertido para qualquer outro tipo e, portanto, usado em locais onde um tipo exato é necessário, por exemplo, em ramos match. Isso permite que escrevamos código como este:

fn main() {
    fn sum_odd_numbers(up_to: u32) -> u32 {
        let mut acc = 0;
        for i in 0..up_to {
            // Note que o tipo de retorno desta expressão match deve ser u32
            // devido ao tipo da variável "addition".
            let addition: u32 = match i%2 == 1 {
                // A variável "i" é do tipo u32, o que está perfeitamente bem.
                true => i,
                // Por outro lado, a expressão "continue" não retorna
                // u32, mas ainda está bem, porque nunca retorna e, portanto,
                // não viola os requisitos de tipo da expressão match.
                false => continue,
            };
            acc += addition;
        }
        acc
    }
    println!("Soma dos números ímpares até 9 (excluindo): {}", sum_odd_numbers(9));
}

Também é o tipo de retorno de funções que loopam para sempre (por exemplo, loop {}), como servidores de rede, ou funções que terminam o processo (por exemplo, exit()).

Resumo

Parabéns! Você concluiu o laboratório de Funções Divergentes. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.