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.
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?
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 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.
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!