@as em Zig — Referência e Exemplos

@as em Zig

O @as é o builtin de conversão explícita de tipos (type cast) do Zig. Ele permite converter um valor de um tipo para outro de forma segura e explícita, garantindo que a conversão é válida. Ao contrário de casts inseguros em C, o @as só permite conversões que o compilador pode verificar como seguras ou que resultam em coerção implícita documentada.

Sintaxe

@as(comptime T: type, valor: anytype) T

O que faz

O @as realiza uma conversão de tipo explícita (type coercion), convertendo o valor fornecido para o tipo de destino especificado. O Zig possui um sistema sofisticado de coerção implícita, e o @as é a forma de invocar esse sistema explicitamente.

Essa conversão é usada quando o compilador não consegue inferir o tipo desejado automaticamente, ou quando o programador deseja tornar a intenção clara no código.

Parâmetros

  • T (type, comptime): O tipo de destino para a conversão. Deve ser conhecido em tempo de compilação.
  • valor (anytype): O valor a ser convertido. Deve ser compatível com o tipo de destino segundo as regras de coerção do Zig.

Valor de retorno

Retorna o valor convertido para o tipo T.

Exemplos práticos

Exemplo 1: Removendo ambiguidade de tipos literais

const std = @import("std");

test "tipo literal com @as" {
    // Literais inteiros são comptime_int — @as define o tipo concreto
    const x = @as(u32, 42);
    try std.testing.expect(@TypeOf(x) == u32);

    // Sem @as, o compilador pode não saber qual tipo usar
    const y = @as(i64, -100);
    try std.testing.expect(@TypeOf(y) == i64);

    // Literais float são comptime_float
    const pi = @as(f32, 3.14159);
    try std.testing.expect(@TypeOf(pi) == f32);
}

Exemplo 2: Conversão em chamadas de função

const std = @import("std");

fn processarBytes(dados: []const u8) usize {
    return dados.len;
}

fn somarF64(a: f64, b: f64) f64 {
    return a + b;
}

test "conversão para argumentos de função" {
    // Converter inteiros para o tipo esperado pela função
    const resultado = somarF64(@as(f64, 10), @as(f64, 20));
    try std.testing.expect(resultado == 30.0);

    // Converter string literal para slice
    const tamanho = processarBytes(@as([]const u8, "hello"));
    try std.testing.expect(tamanho == 5);
}

Exemplo 3: Uso com optionals e error unions

const std = @import("std");

fn buscar(id: u32) ?[]const u8 {
    if (id == 1) return "encontrado";
    return null;
}

test "conversão com optionals" {
    // Converter null para um tipo optional específico
    const valor: ?u32 = @as(?u32, null);
    try std.testing.expect(valor == null);

    // Converter um valor para optional
    const numero: ?u32 = @as(?u32, 42);
    try std.testing.expect(numero.? == 42);

    // Converter para error union
    const resultado: anyerror!u32 = @as(anyerror!u32, 100);
    try std.testing.expect((try resultado) == 100);
}

Casos de uso comuns

  1. Desambiguação de literais: Quando um literal numérico pode ser interpretado como vários tipos, @as define o tipo exato.

  2. Parâmetros de formatação: Em std.debug.print e funções similares, @as garante que os valores no tuple .{} tenham o tipo correto.

  3. Conversão segura entre tipos numéricos: Converter entre tamanhos de inteiros ou entre inteiro e float quando a conversão é segura.

  4. Inicialização de optionals e error unions: Converter null ou valores para tipos optional/error union específicos.

  5. Interoperabilidade: Converter tipos ao chamar funções C importadas que esperam tipos específicos.

const c = @cImport(@cInclude("stdlib.h"));

fn alocar(tamanho: usize) ?[*]u8 {
    return @as(?[*]u8, @ptrCast(c.malloc(tamanho)));
}

Diferença entre @as e outros casts

O @as realiza apenas coerções seguras que o Zig já permitiria implicitamente. Para conversões que alteram a representação ou a interpretação dos dados, existem builtins específicos:

  • @intFromFloat / @floatFromInt — Conversão entre inteiro e float
  • @ptrCast — Conversão entre tipos de ponteiro
  • @intFromPtr / @ptrFromInt — Conversão entre ponteiro e inteiro
  • @truncate — Truncar inteiros para tamanhos menores

Builtins relacionados

Tutoriais relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.