Menu
Try in Playground

Zero While Loops: Iteration in the Agent-First Language

How while loops work in Zero today: the condition, the loop body, the absence of for and do-while in the early language, and what loops have to do with explicit effects.

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

The Basics

while runs its body as long as a bool condition stays true:

while condition {
    // body
}

The compiler evaluates the condition before each iteration:

  • true — run the body, then check again.
  • false — exit the loop.

A trivial illustration from Zero's examples, with a condition that's already false:

Run that and only the second write fires. The body of the while never executes because the condition was false the first time it was checked.

The Condition Is a bool

As with if/else, the loop condition has to be a bool. Zero doesn't coerce integers, strings, or other values into a boolean.

while count {              // compile error
    // ...
}

while count > 0 {          // OK
    // ...
}

The condition can be anything that evaluates to bool: a binding, a comparison, a &&/|| combination, or a function call. The same rules from if apply.

Counted Loops

The classic "do something N times" pattern uses a counter and a while:

let mut i = 0
while i < 10 {
    // do work
    i = i + 1
}

Three pieces: an initial value, a condition that compares against the bound, and an update in the body. This is the pattern every imperative language has — Zero just doesn't dress it up in a for keyword.

A note on the mut spelling above: how Zero spells mutable bindings in your toolchain may differ in pre-1.0 versions. Run zero check --json against a small test to confirm the exact syntax your compiler accepts. The conceptual pattern (counter + condition + update) is the part that's stable.

Infinite Loops

A while whose condition is always true runs forever:

while true {
    // wait for work, handle it, loop again
}

This is the right shape for an event loop, a REPL, or a long-running server. To exit, you either terminate the process, raise an error out of the body, or restructure to break the condition.

When to Reach for a Loop

Loops are a tool to use sparingly. Things that look like loops in other languages often have a cleaner shape in Zero:

  • Iterating over a fixed collection: prefer a function that the standard library or your shape exposes — a forEach-style helper, a folder, or a recursive walk.
  • Reading until end-of-input: loop on a fallible read, but use check and raises to handle the boundary cleanly rather than nesting status flags.
  • Polling for a condition: consider whether the design should hand you a signal instead. Polling loops are a smell in any systems language.

The same instinct applies to agents: a tight, declarative shape is easier to reason about than a hand-written counter loop, both for humans and for code generators.

Loops and Effects

A while body, like any other block, can do I/O — but only if it has access to a World capability (or a slice of one). A function whose signature doesn't mention World can loop all it wants but can't write anything to the outside. That property holds inside the loop body too; the loop doesn't grant any new capabilities.

This sounds obvious, but it's the reason you can put a while inside a "pure" computation function and still know — from the signature alone — that it can't print anything or write to disk.

Style Notes

A few small habits that pay off:

  • Keep the condition obvious. If the condition is doing real work, lift it into a named function or binding so the loop reads cleanly.
  • Update the counter at the bottom of the body, not scattered through it. Easier to spot off-by-one bugs.
  • Prefer early-exit conditions you can express as the loop's own condition over flags that flip mid-iteration. Fewer moving parts.

Next: Shapes

You've now seen Zero's core control flow. The next chapter is about modeling data — starting with shapes, Zero's struct-like product types.

Frequently Asked Questions

How do while loops work in Zero?

Use while condition { ... }. The condition is evaluated before each iteration; if it's true, the body runs and the loop checks again. If it's false, the loop exits and execution continues after the closing brace. The condition has to be a bool.

Does Zero have a for loop?

Early Zero ships while as its only loop construct. The language deliberately keeps the surface small while it stabilizes — fewer keywords means fewer ways for an agent to pick the wrong form. A for over a range or collection may land later; until then, you build the same pattern with while and a counter.

How do you write a counted loop in Zero?

Initialize a counter, run a while against it, and update inside the body: let mut i = 0; while i < 10 { ...; i = i + 1 }. Mutability syntax is still evolving in pre-1.0 Zero, so check the current docs for the exact spelling — but the pattern of while + counter + update is the standard counted-loop idiom.

Is there a break or continue in Zero?

Most languages in Zero's family ship some early-exit construct for loops; the exact spelling in pre-1.0 Zero is one of the areas that may move before 1.0. The conservative approach is to structure the loop so the condition itself does the work — invert and update the condition so the loop naturally exits — rather than relying on a specific control-flow keyword.

Can a Zero while loop run forever?

Yes — while true { ... } is an infinite loop. Useful for servers, event loops, REPLs, anything where you don't have a natural termination condition. Unlike implicit truthiness, true here is a literal of type bool so the condition is still well-typed.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED