Los tipos integrados
Zero te da un conjunto pequeño y regular de tipos primitivos. Nada exótico, nada sorprendente: solo los que cualquier lenguaje de sistemas necesita, nombrados con coherencia.
| Familia | Tipos | Notas |
|---|---|---|
| Enteros con signo | i8, i16, i32, i64 | Complemento a dos. |
| Enteros sin signo | u8, u16, u32, u64 | Solo 0 y positivos. |
| Del tamaño del puntero | usize, isize | El ancho coincide con el puntero de la plataforma. |
| Flotantes | f32, f64 | IEEE-754. |
| Booleano | bool | true o false. |
| Carácter | char | Un único escalar Unicode. |
| Cadena | String | Cadena UTF-8. |
| Vacío | Void | "Sin valor útil." |
Esa es toda la lista de primitivos que tocarás día a día. Los tipos compuestos — shapes, enums, choices — se construyen a partir de estos.
Enteros
Los tipos enteros siguen un patrón de nombres uniforme: i para con signo, u para sin signo, seguido del ancho en bits. Así, i32 es un entero con signo de 32 bits; u8 es un byte sin signo; i64 es un entero con signo de 64 bits.
let small_signed: i8 = -120
let byte: u8 = 250
let id: i32 = 1
let big: i64 = 9_000_000_000
let index: usize = 0
Lo que viene por defecto para un literal sin sufijo es i32, a menos que el contexto fuerce otra cosa:
let answer = 42 // i32
Cuando necesitas un ancho específico, añade un sufijo al literal o anota la ligadura:
let byte = 250_u8 // literal tipado
let byte: u8 = 250 // ligadura tipada
Ambas formas producen el mismo valor. La forma con sufijo en el literal viene bien cuando estás pasando un literal directamente a una función o construyendo un struct:
let pair: BytePair = Pair { left: 1_u8, right: 2_u8 }
Qué ancho elegir
Una regla rápida:
i32para la mayoría de la aritmética con signo. Lo bastante ancho para casi todo lo que vayas a contar, rápido en cualquier plataforma.u8para trabajo a nivel de byte. Bytes de un archivo, bytes en un buffer, bytes por red.u32/u64para conteos no negativos cuando importa el rango. Offsets de archivo por encima de 2 GB, conteos grandes.usizepara tamaños e índices. Del tamaño del puntero: coincide con lo que usa la plataforma para direccionar memoria.i64para tiempo desde epoch y similares. Lo bastante grande para nanosegundos durante cientos de años.
Elegir el tipo más pequeño que entre es buena práctica; elegir un tipo demasiado pequeño y desbordar es un problema mucho mayor que pasarse por un bit.
Booleanos
let ok = true
let done: bool = false
bool tiene exactamente dos valores: true y false. Son literales, no constantes que importes de algún sitio. La condición de un if o un while es un bool — no hay truthiness implícita para enteros o cadenas.
if ok {
check world.out.write("sí\n")
} else {
check world.out.write("no\n")
}
If/else cubre los condicionales en detalle.
Flotantes
f32 y f64 son números en coma flotante IEEE-754 de 32 y 64 bits respectivamente. Úsalos cuando necesites valores fraccionarios: medidas, ratios, geometría. Para aritmética exacta sobre dinero, prefiere enteros en la unidad más pequeña (céntimos, satoshis) antes que flotantes.
let ratio: f32 = 0.5
let pi: f64 = 3.141592653589793
f64 es lo que viene por defecto para literales de flotante sin sufijo.
Caracteres y cadenas
Un char guarda un único valor escalar Unicode:
let initial: char = 'Z'
Un String es una secuencia de caracteres, codificada típicamente como UTF-8 por la biblioteca estándar. Los literales de cadena usan comillas dobles:
let message: String = "hola desde zero\n"
Funcionan las secuencias de escape esperables: \n para salto de línea, \t para tab, \\ para una barra invertida literal, \" para una comilla doble literal.
let multi_line = "línea uno\nlínea dos\n"
La biblioteca estándar expone vistas a nivel de byte sobre una cadena para trabajo de bajo nivel. La forma std.mem.span("zero") devuelve un Span<u8> sobre los bytes — útil cuando estás parseando, haciendo hashing o comparando byte a byte.
Void
Void es el tipo "sin valor de retorno útil" de Zero. Las funciones que existen por sus efectos lo usan:
pub fun main(world: World) -> Void raises {
check world.out.write("hola\n")
}
main escribe algo y vuelve. No hay un valor que devolver, así que el tipo es Void. Verás Void en la mayoría de las funciones que tocan World: están elegidas por su efecto, no por su resultado.
Guiones bajos en literales numéricos
Los literales numéricos largos pueden usar guiones bajos como separadores visuales. El compilador los ignora, así que son una característica puramente de legibilidad:
let big = 9_000_000_000_i64
let bytes = 1_048_576_u32 // 1 MiB
Úsalos donde los dígitos se hagan difíciles de contar.
Chuleta de sufijos para literales tipados
| Sufijo | Tipo | Ejemplo |
|---|---|---|
_i8 / _i16 / _i32 / _i64 | Entero con signo | 127_i8 |
_u8 / _u16 / _u32 / _u64 | Entero sin signo | 255_u8 |
_usize / _isize | Tamaño del puntero | 0_usize |
_f32 / _f64 | Flotante | 0.5_f32 |
Échales mano cuando construyas un valor en el que el contexto no fija el tipo.
Lo siguiente: funciones
Los primitivos no sirven de nada sin algo que hacer con ellos. La próxima página cubre las funciones en Zero: cómo declararlas, devolver valores desde ellas y combinarlas para construir programas reales.
Preguntas frecuentes
¿Qué tipos primitivos tiene Zero?
Zero trae enteros con signo dimensionados i8, i16, i32, i64; enteros sin signo u8, u16, u32, u64; enteros del tamaño del puntero usize e isize; flotantes f32 y f64; bool; char; String; y Void para funciones que no devuelven nada útil.
¿Cuál es el tipo entero por defecto en Zero?
Un literal entero sin sufijo como 42 por defecto es i32 a menos que el contexto fuerce otro tipo. Para usar un ancho específico, escribe el literal con un sufijo como 42_u8 o 42_i64, o anota el tipo de la ligadura explícitamente con let count: u8 = 42.
¿Tiene Zero un tipo cadena separado?
Sí. Los literales de cadena como "hola" tienen un tipo cadena integrado que la biblioteca estándar trata como una secuencia de bytes (habitualmente UTF-8). Para trabajo de bajo nivel a nivel de byte, la biblioteca estándar expone spans y utilidades de bytes; para operaciones a nivel de carácter existe char para valores escalares individuales.
¿Qué significa Void en Zero?
Void es el tipo de retorno de una función que no produce un valor útil: existe únicamente por sus efectos. La firma convencional pub fun main(world: World) -> Void raises usa Void porque main existe para hacer E/S y salir, no para producir un valor.
¿Cuál es la diferencia entre i32 y u32 en Zero?
i32 es un entero con signo de 32 bits con rango −2.147.483.648 a 2.147.483.647. u32 es sin signo y tiene el rango 0 a 4.294.967.295. Usa tipos con signo cuando los valores negativos tienen sentido; sin signo cuando los negativos serían un bug — para conteos, índices, tamaños, etc.