Introdução a Zig - Parte 3

Estruturas concionais

Enzo Soares

Publicado em 21 de Março de 2025 às 19:44

Olá!

Hoje falaremos de estruturas condicionais no Zig e e as ferramentas que essa última nos proporciona para fazer otimizações! Vamos começar.

if

O if é estrutura mais básica condicinal. Ele valida a codição definida entre parênteses e, se ela for verdadeira, executa o código entre chaves. No código abaixo, caso a seja diferente de b, define o valor de result para 1.

    const a: u32 = 5;
    const b: u32 = 4;
    var result: u32 = 0;

    if (a != b) {
        result = 1;
    }

Estruturas condicionais também podem colapsar uniões de erro e uniões opcionais:

    const b: anyerror!u32 = funcao();
    if (b) |value| {
        fazerAlgumaCoisa(value);
    }

Na primeira linha, temos um tipo que é a união entre u32 e um erro qualquer. O if transforma b em value, que passa a ter apenas o tipo u32. Essa abordagem representa uma grande vantagem em relação à maioria das outras linguagens de programação, pois o Zig nos obriga a definir explicitamente todas as variáveis que podem receber valores nulos (null). Dessa forma, temos clareza e certeza sobre quais variáveis podem ser nulas e quais não podem, aumentando a segurança e a robustez do código.

O fato de qualquer variável poder receber o valor de null já foi acusado de ser o maior erro da ciência do computação. Eu acho essa afirmação meio exagerada, mas entendo o sentimento.

Temos duas outras estruturas relacionadas ao if: o else if e o else.

O else if nos permite definir uma condição que será avaliada após a anterior ter sido definida como falsa e vários else if podem ser encadeados para fazer lógicas complexas. Já o else apenas é executado quando todas as estruturas anteriores foram falsas:

    const a: u32 = 5;
    const b: u32 = 4;
    if (a - b == 2) {
        unreachable;
    } else if (a - b == 1) {
        fazerAlgo();
    } else if (a - b == 0) {
        unreachable;
    } else {
        unreachable;
    }

No exemplo anterior, dados os valores de a e de b, apenas o bloco de código fazerAlgo(); é executável. Por isso, todos os outros caminhos foram marcados como unreachable. Mas o que é isso?

unreachable

Essa palavra reservada nada mais é uma indicação ao compilador de que aquele pedaço de código nunca vai ser executado. Caso seja executado, o compilador pode ou lançar um erro ou executar mais lentamente, dependependo da forma como o código foi compilado. ´unreachable´ é ótimo para legibilidade do código e para performance, pois o compilador pode otimizar para nunca ter que fazer aquela operação.

Ternários

Ternários são estruturas condicionais simples feitas para caberem em uma só linha. Elas fazem uma comparação: se verdadeira, retornam algo. Se não, retornam outro algo.

    const result = if (a != b) 47 else 3089;

O ternário pode ser explicado como: se b for diferente a a, defina result como 47. Se não, como 3089.

Pode ser tentador colocar vários ternários na mesma linha para reproduzir uma estrutura condicional complexa, mas isso pode sair de mão rapidamente. O uso excessivo de ternários pode reduzir a legibilidade do seu código.

switch

O switch é uma estrutura condicional que te permite comparar várias afirmações contra um único e imutável valor. Observe o exemplo:

    const resultado = switch (valorImutavel) {
        0 => -1,

        // Múltiplos casos podem ser combinados com ','
        1, 2, 3 => 0,

        // '..' indica um intervalo entre 5 e 100, incluso 5 e 100
        5...100 => 1,

        // Caso o bloco de código seja complexo, ele pode ser separado por chaves
        101 => {
            return fazerAlgumaCoisa();
        },
        // Indica o que será executado caso todas as comparações possíves resultem em falso
        else => 9,
    };

O valor a ser comparado tem o nome, no exemplo, de valorImutavel. A expressão antes de => indica o valor a ser comparado contra valorImutavel. Já a expressão depois de => indica o que será executado caso a comparação resulte em verdadeiro.

Caso o switch não trate de todos os casos possíveis e não tenha um else, será lançado um erro de compilação:

    const valorImutavel = 4;
    const resultado = switch (valorImutavel) {
        0 => -1,

        // Múltiplos casos podem ser combinados com ','
        1, 2, 3 => 0,
    };

Isso é tudo por hoje. Obrigado!