Menu

Zero If/Else: Conditional Branching Explained

How if and else work in Zero: boolean conditions, branch bodies, the absence of truthy coercion, and how conditionals fit alongside match for richer branching.

This page includes runnable editors — edit, run, and see output instantly.

The Basics

if in Zero looks roughly like if in every other C-family language, with one notable restriction: the condition must be a bool.

The condition value == 42 is a bool because == between two i32s returns a bool. The two arms each contain a block of statements. Either arm can be omitted-ish — the else is optional — but when both are present, both have to be { ... } blocks.

The bool Requirement

Some languages let you write if value { ... } and treat 0, "", or null as falsy. Zero doesn't. The condition has to be an actual bool.

let count = 0
if count {              // compile error: expected bool, got i32
    // ...
}

if count == 0 {         // OK
    check world.out.write("nothing to do\n")
}

The reason is the same one running through the rest of the language: explicit beats implicit. An agent reading the second form knows exactly what's being checked. The first form leaves the truthiness rules implicit and varies across languages — Zero opts out.

Else and Else-If

The else clause runs when the condition is false:

Chain conditions with else if:

if value < 0 {
    check world.out.write("negative\n")
} else if value == 0 {
    check world.out.write("zero\n")
} else {
    check world.out.write("positive\n")
}

else if is just else { if ... } with the braces left out — same semantics, less indentation. The final else is optional.

Where the Condition Comes From

The condition can be anything that evaluates to bool:

  • A bool binding: if ok { ... }.
  • A comparison: if value == 42 { ... }, if x < y { ... }.
  • A logical combination: if a && b { ... }, if pair.left == 1_u8 && pair.right == 2_u8 { ... }.
  • A function call that returns bool: if isReady(world) { ... }.

A real-world snippet from the language's examples:

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")
}

The && short-circuits the way you'd expect — if the left side is false, the right side isn't evaluated. Same for ||.

When to Use match Instead

if/else if chains are fine for binary or three-way decisions, especially when the conditions don't share structure. But when you're branching on the variants of a sum type — a choice or enummatch is the right tool.

Compare:

// match — exhaustive, compiler-checked
match result {
    .ok  => value   { check world.out.write("ok\n") }
    .err => message { check world.out.write("err\n") }
}

vs.

// if/else over a sum type — verbose and easier to get wrong
if result.isOk() {
    let value = result.unwrap()
    check world.out.write("ok\n")
} else {
    check world.out.write("err\n")
}

The match form makes the variant analysis explicit and the compiler will complain if a variant is added later and you forget to handle it. The if form silently passes anything that isn't ok through to the else branch, even brand-new variants you've never thought about.

Rule of thumb: if for booleans, match for variants.

Stylistic Notes

A few small conventions that make code easier for both humans and agents to read:

  • Always brace the body. Even a one-line body goes in { ... }. There is no braceless single-statement form. This is on purpose — it keeps indentation reliable and removes a common source of bugs across the C-family.
  • Put the most common branch first. Readers (and agents) skim top to bottom.
  • Prefer positive conditions when they're as clear. if isReady is easier to follow than if !notReady, all else equal.

Next: While Loops

Conditionals decide what to do; loops decide how many times to do it. The next doc covers Zero's while loops, the early-stage looping construct the language ships with.

Frequently Asked Questions

How do if statements work in Zero?

Use if condition { ... } with an optional else { ... } clause. The condition has to be a bool — Zero does not coerce integers, strings, or other values to a boolean. Example: if value == 42 { check world.out.write("yes\n") } else { check world.out.write("no\n") }.

Does Zero have a ternary operator?

Zero deliberately keeps the surface small and uses if / else blocks rather than a separate condition ? a : b ternary. The official examples favor explicit branches even for short cases. If your language supports if-as-expression, expect Zero to lean toward that direction rather than introducing a second syntax.

Can you chain if/else if in Zero?

Yes. Chain conditions by writing else if between branches: if a { ... } else if b { ... } else { ... }. For more elaborate branching over a choice or enum, reach for match instead — it's more exhaustive and the compiler checks that you handled every variant.

Why doesn't Zero coerce values to bool?

Zero's design philosophy is 'everything is explicit'. Implicit truthiness — treating 0, "", or null as false — is a frequent source of bugs and is hard for an agent to reason about precisely. Requiring an actual bool makes the branching decision visible in the source and easier to verify mechanically.

When should you use match instead of if/else?

Use match when you're branching on the variants of a choice or enum. The compiler can verify you've covered every case, which if/else if chains can't. Keep if/else for simple boolean predicates — equality checks, comparisons, and short two-way branches.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED