Una sola forma de nombrar un valor
En Zero, le das un nombre a un valor con let:
let answer = 42
Esa es toda la sintaxis. No hay var, no hay const, no hay auto. Una sola palabra clave para ligaduras mantiene el lenguaje pequeño: tanto agentes como humanos la aprenden una vez y la aplican en todas partes.
let introduce una ligadura local en el ámbito actual. Tras esa línea, answer se refiere a 42 hasta el final del bloque que lo contiene.
Inferencia de tipos
El compilador infiere el tipo a partir del lado derecho. El literal 42 tiene tipo i32 por defecto, así que answer es un i32. El literal "hola" es una cadena, de modo que:
let greeting = "hola"
vincula greeting a un valor de tipo cadena. Si llamas a una función que devuelve un Pair<i32, u8>, la ligadura tiene tipo Pair<i32, u8>:
let pair = makePair(40, 2_u8)
No tienes que escribir el tipo en cada ligadura, lo que mantiene el código legible.
Anotaciones de tipo explícitas
Cuando quieras documentar el tipo — o forzar uno concreto cuando la inferencia escogería otra cosa — escribe el tipo tras dos puntos:
let count: u8 = 10
let pair: Pair<i32, u8> = makePair(40, 2_u8)
Las anotaciones también son una pista para el compilador cuando un literal podría ser de varios tipos. El literal 10 podría ser i32, i64, u8, etc.; la anotación lo fija.
También verás sufijos de tipo en los literales como alternativa a anotar la ligadura:
let small = 10_u8 // u8 por el sufijo del literal
let big = 10_i64 // i64 por el sufijo del literal
Ambas formas son válidas; elige la que deje más clara la intención en el sitio de la llamada.
Ligaduras en acción
Un ejemplo trabajado usando las formas inferida y explícita — pulsa Ejecutar para probarlo:
point se anota explícitamente porque el lado derecho es un literal de struct. total se infiere — sum declara que devuelve i32, así que la ligadura también es i32.
Ámbito y sombreado
Una ligadura let es válida desde la línea que la declara hasta el final de su bloque contenedor. Los bloques anidados crean nuevos ámbitos:
pub fun main(world: World) -> Void raises {
let value = 1
if true {
let value = 2 // sombrea el 'value' externo dentro de este bloque
// aquí, value == 2
}
// fuera del if otra vez, value == 1
}
El value interno no muta al externo: es una ligadura distinta que sale de ámbito al cerrar la llave del bloque if. Es el mismo modelo que en Rust y los lenguajes de la familia ML. Resulta especialmente común cuando quieres transformar un valor a través de una serie de pasos sin inventar nombres nuevos para cada resultado intermedio.
Lo que let no hace
Algunas cosas que podrías esperar de otros lenguajes y que let deliberadamente no incluye:
- Declaraciones solo de tipo. No existe una forma
let x: i32;que introduzca una ligadura sin valor. Una ligadura debe tener un valor en el punto en que se declara. - Destructuración por patrones (todavía). Algunos lenguajes te dejan escribir
let (a, b) = pair. Zero es pequeño por diseño y se centra de momento en ligaduras de nombre simples — consulta la documentación actual para ver si ya llegó la destructuración. - Varias palabras clave para distintos tiempos de vida. No hay variantes
static,const,let mutni de ámbito de bloque vs. ámbito de función separadas. Una sola palabra clave.
Si vienes de JavaScript, la analogía más cercana es const: un nombre ligado a un valor durante el resto del bloque, con sombreado en ámbitos internos. Si vienes de Rust, el let de aquí cumple el mismo papel que el let de Rust menos la palabra clave explícita mut.
Un patrón: construir un valor paso a paso
Las ligaduras brillan cuando quieres escribir un cómputo como una serie de pasos intermedios con nombre. Eso es bueno tanto para humanos que leen como para agentes que razonan localmente sobre cada línea:
Cada línea introduce un hecho nuevo con el que trabaja el resto de la función. El compilador sigue produciendo código compacto: nombrar los valores intermedios no tiene coste en tiempo de ejecución.
Lo siguiente: tipos primitivos
let no significa mucho sin algo que ligar. La próxima página recorre los tipos primitivos de Zero — los anchos de entero, los flotantes, las cadenas y los tipos Void y Bool que verás más a menudo.
Preguntas frecuentes
¿Cómo se declara una variable en Zero?
Con let. La forma es let name = value para un tipo inferido, o let name: Type = value para escribir el tipo explícitamente. Por ejemplo: let answer = 42 o let answer: i32 = 42. Ambas vinculan el nombre answer al valor 42 en el ámbito actual.
¿Zero infiere los tipos en las ligaduras let?
Sí. Si escribes let total = sum(point) y sum devuelve i32, el tipo de la ligadura se infiere como i32. Puedes anotarlo explícitamente cuando quieras documentar el tipo o forzar uno concreto — por ejemplo let count: u8 = 10.
¿Las ligaduras let de Zero son mutables?
Un let sin más introduce una ligadura local para usar dentro de su ámbito. La historia de la mutabilidad en Zero pre-1.0 aún está evolucionando — el lenguaje prima los efectos explícitos y la memoria predecible, así que todo lo que mute estado a través de una ligadura tiene que hacerlo visible. Consulta la documentación actual de Zero para la sintaxis exacta de mutabilidad en tu versión del toolchain.
¿Cuál es la diferencia entre let y const en Zero?
Zero usa let para las ligaduras locales habituales dentro del cuerpo de una función. No expone varias palabras clave de ligadura como let/const/var de JavaScript — mantener la superficie pequeña es una decisión de diseño deliberada. Las constantes de compilación suelen expresarse a través del sistema de tipos o de declaraciones de nivel superior, no con una palabra clave aparte.
¿Se puede redeclarar una ligadura let en Zero?
Las ligaduras viven dentro de su ámbito contenedor. Un nuevo let con el mismo nombre en un ámbito anidado es una ligadura distinta que sombrea la externa durante la duración del ámbito interno — la externa queda intacta al cerrarse el bloque interno. Es el mismo modelo que usan Rust y los lenguajes de la familia ML.