Menu

If/Else en Zero: ramificación condicional explicada

Cómo funcionan if y else en Zero: condiciones booleanas, cuerpos de cada rama, la ausencia de coerción a verdadero/falso y cómo encajan los condicionales junto a match para ramificaciones más ricas.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Lo básico

if en Zero se parece bastante al if de cualquier otro lenguaje de la familia C, con una restricción notable: la condición debe ser un bool.

La condición value == 42 es un bool porque == entre dos i32 devuelve un bool. Las dos ramas contienen un bloque de instrucciones cada una. Cualquier rama puede omitirse — else es opcional —, pero cuando están las dos, ambas tienen que ser bloques { ... }.

El requisito de bool

Algunos lenguajes te dejan escribir if value { ... } y tratan 0, "" o null como falsos. Zero no. La condición tiene que ser un bool de verdad.

let count = 0
if count {              // error de compilación: se esperaba bool, recibido i32
    // ...
}

if count == 0 {         // OK
    check world.out.write("nada que hacer\n")
}

El motivo es el mismo que atraviesa el resto del lenguaje: lo explícito le gana a lo implícito. Un agente que lea la segunda forma sabe exactamente qué se está comprobando. La primera deja implícitas las reglas de truthiness y estas varían según el lenguaje — Zero pasa.

Else y else-if

La cláusula else se ejecuta cuando la condición es falsa:

Encadena condiciones con else if:

if value < 0 {
    check world.out.write("negativo\n")
} else if value == 0 {
    check world.out.write("cero\n")
} else {
    check world.out.write("positivo\n")
}

else if es solo else { if ... } sin las llaves: misma semántica, menos indentación. El else final es opcional.

De dónde sale la condición

La condición puede ser cualquier cosa que evalúe a bool:

  • Una ligadura bool: if ok { ... }.
  • Una comparación: if value == 42 { ... }, if x < y { ... }.
  • Una combinación lógica: if a && b { ... }, if pair.left == 1_u8 && pair.right == 2_u8 { ... }.
  • Una llamada a función que devuelva bool: if isReady(world) { ... }.

Un fragmento real de los ejemplos del lenguaje:

let pair: BytePair = Pair { left: 1_u8, right: 2_u8 }
if pair.left == 1_u8 && pair.right == 2_u8 {
    check world.out.write("type alias ok\n")
} else {
    check world.out.write("type alias broke\n")
}

&& cortocircuita como esperarías: si el lado izquierdo es false, el derecho no se evalúa. Lo mismo con ||.

Cuándo usar match en su lugar

Las cadenas if/else if van bien para decisiones binarias o de tres vías, sobre todo cuando las condiciones no comparten estructura. Pero cuando estás ramificando sobre las variantes de un tipo suma — un choice o un enum —, match es la herramienta adecuada.

Compara:

// match — exhaustivo, comprobado por el compilador
match result {
    .ok  => value   { check world.out.write("ok\n") }
    .err => message { check world.out.write("err\n") }
}

frente a:

// if/else sobre un tipo suma — verboso y más fácil de equivocar
if result.isOk() {
    let value = result.unwrap()
    check world.out.write("ok\n")
} else {
    check world.out.write("err\n")
}

La forma match hace explícito el análisis de variantes y el compilador se quejará si añades una variante después y olvidas manejarla. La forma if pasa silenciosamente cualquier cosa que no sea ok a la rama else, incluidas variantes nuevas en las que nunca pensaste.

Regla rápida: if para booleanos, match para variantes.

Notas de estilo

Algunas convenciones pequeñas que facilitan la lectura tanto a humanos como a agentes:

  • Pon siempre llaves al cuerpo. Incluso un cuerpo de una línea va en { ... }. No hay forma de una sola instrucción sin llaves. Es a propósito: mantiene la indentación fiable y elimina una fuente común de bugs en la familia C.
  • Pon primero la rama más común. Quien lee (y los agentes) escanea de arriba hacia abajo.
  • Prefiere condiciones positivas cuando sean igual de claras. if isReady se sigue mejor que if !notReady, en igualdad de condiciones.

Lo siguiente: bucles while

Los condicionales deciden qué hacer; los bucles deciden cuántas veces hacerlo. La próxima página cubre los bucles while de Zero, el constructo de iteración con el que arranca el lenguaje en su etapa temprana.

Preguntas frecuentes

¿Cómo funcionan las instrucciones if en Zero?

Usa if condition { ... } con una cláusula else { ... } opcional. La condición tiene que ser un bool: Zero no convierte enteros, cadenas u otros valores a booleano. Ejemplo: if value == 42 { check world.out.write("sí\n") } else { check world.out.write("no\n") }.

¿Tiene Zero operador ternario?

Zero mantiene deliberadamente la superficie pequeña y usa bloques if / else en lugar de un ternario condition ? a : b. Los ejemplos oficiales prefieren ramas explícitas incluso para casos cortos. Si tu lenguaje soporta if como expresión, espera que Zero tienda en esa dirección antes que introducir una segunda sintaxis.

¿Se puede encadenar if/else if en Zero?

Sí. Encadena condiciones escribiendo else if entre ramas: if a { ... } else if b { ... } else { ... }. Para ramificaciones más elaboradas sobre un choice o enum, usa match en su lugar — es más exhaustivo y el compilador comprueba que has manejado cada variante.

¿Por qué Zero no convierte valores a bool?

La filosofía de diseño de Zero es 'todo es explícito'. La truthiness implícita — tratar 0, "" o null como falso — es fuente frecuente de bugs y difícil de razonar con precisión para un agente. Exigir un bool real hace visible la decisión de ramificación en el código y facilita verificarla mecánicamente.

¿Cuándo usar match en lugar de if/else?

Usa match cuando ramificas sobre las variantes de un choice o un enum. El compilador puede verificar que has cubierto cada caso, cosa que las cadenas if/else if no pueden. Reserva if/else para predicados booleanos simples: comparaciones de igualdad, comparaciones y ramificaciones cortas de dos vías.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR