Menu

Tipos primitivos de Zero: enteros, flotantes, Bool, String y Void

Los tipos integrados que Zero te da de fábrica: enteros con signo y sin signo de cualquier ancho, flotantes, booleanos, caracteres, cadenas y el tipo vacío Void.

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.

FamiliaTiposNotas
Enteros con signoi8, i16, i32, i64Complemento a dos.
Enteros sin signou8, u16, u32, u64Solo 0 y positivos.
Del tamaño del punterousize, isizeEl ancho coincide con el puntero de la plataforma.
Flotantesf32, f64IEEE-754.
Booleanobooltrue o false.
CaráctercharUn único escalar Unicode.
CadenaStringCadena UTF-8.
VacíoVoid"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:

  • i32 para 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.
  • u8 para trabajo a nivel de byte. Bytes de un archivo, bytes en un buffer, bytes por red.
  • u32 / u64 para conteos no negativos cuando importa el rango. Offsets de archivo por encima de 2 GB, conteos grandes.
  • usize para tamaños e índices. Del tamaño del puntero: coincide con lo que usa la plataforma para direccionar memoria.
  • i64 para 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

SufijoTipoEjemplo
_i8 / _i16 / _i32 / _i64Entero con signo127_i8
_u8 / _u16 / _u32 / _u64Entero sin signo255_u8
_usize / _isizeTamaño del puntero0_usize
_f32 / _f64Flotante0.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.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR