¿Qué es un zig language type system?

¿Qué es un zig language type system?

El lenguaje de programación Zig ofrece un sistema de tipos que combina la rigidez del tipado estático con la flexibilidad del tipado dinámico en tiempo de compilación. Este sistema permite que los programas sean seguros, eficientes y expresivos, al tiempo que facilita la depuración y la optimización del código.

Conceptos Fundamentales del Sistema de Tipos Zig

  • Tipado estático: Todos los tipos se verifican en tiempo de compilación.
  • Tipado fuerte: No se permiten conversiones implícitas entre tipos incompatibles.
  • Tipado con inferencia limitada: Zig infiere tipos en ciertos contextos pero siempre se puede especificar explícitamente.
  • Tipado en tiempo de compilación (comptime): Muchas operaciones sobre tipos se realizan en el compilador.
  • Tipado genérico: Se utilizan plantillas de tipos que se especializan en tiempo de compilación.

Tipos de Datos Primarios

  • Enteros sin signo: u8, u16, u32, u64, u128
  • Enteros con signo: i8, i16, i32, i64, i128
  • Coma flotante: f16, f32, f64, f128
  • Booleano: bool
  • Caracteres: u8 (ASCII), u32 (Unicode scalar)

Ejemplo: Definición y Uso de Tipos Primitivos

// Definición de variables con tipos primitivos
const a: u32 = 42;           // a es un entero sin signo de 32 bits
const b: f64 = 3.14159;      // b es un número de punto flotante de doble precisión
const c: bool = true;        // c es un valor booleano
const d: u8 = 255;           // d es el mayor valor posible de u8 (8 bits)

// Imprimimos los valores para comprobar
std.debug.print("a = {}\n", .{a});
std.debug.print("b = {}\n", .{b});
std.debug.print("c = {}\n", .{c});
std.debug.print("d = {}\n", .{d});

En este fragmento:

  • const indica una variable inmutable.
  • Los tipos se especifican después del nombre con :.
  • Las funciones de impresión utilizan el motor de formato de Zig, donde {} es el marcador de posición.
  • El punto . después del primer argumento de print indica que el segundo argumento es una tupla de valores a formatear.

Tipos de Datos Estructurados

Zig permite crear estructuras y uniones, así como enumeraciones que son fundamentales para la organización de datos complejos.

Estructuras

const Point = struct {
    x: f64,
    y: f64,
};

var p: Point = .{ .x = 1.0, .y = 2.0 };

// Acceso a campos
std.debug.print("Point p: ({}, {})\n", .{p.x, p.y});

Explicación:

  • La palabra clave struct define un nuevo tipo compuesto.
  • Los campos se enumeran con nombre: tipo.
  • La inicialización con .{ .campo = valor } es obligatoria y explícita.
  • El operador . antes de x y y accede a los campos de la estructura.

Uniones

const Value = union(enum) {
    int: i32,
    float: f32,
    bool: bool,

    // Método para convertir a string
    fn toString(self: Value) []const u8 {
        return switch (self) {
            .int => "int",
            .float => "float",
            .bool => "bool",
        };
    }
};

var v: Value = .{ .int = 7 };
std.debug.print("Value type: {}\n", .{v.toString()});

Notas:

  • Una union(enum) combina la semántica de una unión con un discriminador enumerado.
  • La etiqueta self es la referencia al propio valor.
  • El switch permite seleccionar el caso activo y ejecutar código correspondiente.

Enumeraciones

const Color = enum(u8) {
    Red = 1,
    Green,
    Blue,
};

var c: Color = .Green; // Green toma el valor 2 automáticamente
std.debug.print("Color Green = {}\n", .{@intFromEnum(c)});

Detalles:

  • El tipo subyacente u8 determina el tamaño del enumerador.
  • Los valores sucesivos se incrementan automáticamente si no se especifican explícitamente.
  • La función @intFromEnum convierte el valor de enum a su representación entera.

Tipos de Puntero y Referencia

Zig diferencia claramente entre punteros que pueden ser nulos y punteros no nulos. Además, permite punteros a tipos genéricos y punteros constantes.

Puntero Nulo y No Nulo

var num: i32 = 10;

// Puntero no nulo (constante)
var ptr: *const i32 = #

// Puntero nulo (opcional)
var opt_ptr: ?*i32 = null;

// Asignamos una dirección válida
opt_ptr = #

// Acceso mediante desreferenciación segura
if (opt_ptr) |p| {
    std.debug.print("Valor a través del puntero: {}\n", .{p.*});
}

Explicación de la sintaxis:

  • *const i32 indica un puntero a un entero que no puede modificarse.
  • ?*i32 representa un puntero opcional que puede ser null.
  • El operador .* desreferencia un puntero.
  • El patrón if (opt_ptr) |p| { ... } es una forma segura de comprobar la presencia de un puntero.

Tipos Funcionales

En Zig, las funciones son primero clase de ciudadanos y su tipo se describe por los tipos de los parámetros y el tipo de retorno.

Definición de Funciones

fn add(a: i32, b: i32) i32 {
return a + b;
}

// Declaración de un puntero a función
var fn_ptr: fn (i32, i32) i32 = add;

// Llamada a través del puntero
const result = fn_ptr(3, 4);
std.debug.print("Resultado de add via ptr: {}\

Comments

No comments yet. Why don’t you start the discussion?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *