This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.

Control

import std/control

Koru Standard Library: Control Flow

control.kz · 5 tors · ~[comptime]

Koru Standard Library: Control Flow Provides if for zero-overhead conditional branching ARCHITECTURE: if is a pure comptime transform that generates inline Zig code. - if(expr) | then |> ... | else |> ... becomes a literal if/else statement - No function call overhead, full access to outer scope - Uses template_utils.lookupTemplate + interpolate for metaprogramming!

~part targets koru_std/control.targets.kz

Koru Standard Library: the `targets` part of control.kz. Joined via `~part targets` in control.kz; merged into the control module at load. The NON-zig template bodies of control.kz's three keywords — the |js and |cs variants of if, cond, for. They share one home because their surfaces converge: if/cond bodies are byte-identical across hosts (the js comment below already argued "shared, not re-derived"), and a fix that lands in one lowering path has to land in all of them — one file is where a sweep actually sees that. The tor decls and the |zig originals stay in control.kz. JS variant of if. The per-call render is target-blind to the EMITTER (the body is spliced inline before variant selection), so the RENDERER selects THIS variant when --lang=js. The body is byte-identical to the Zig one — JS `if/else` shares the same surface — but it is now HONESTLY the JS variant, not a Zig-body leak that happened to also be valid JS. The `__koru_continue_N` markers it mints are resolved by js_emitter's emitInlineBodyResolvingContinuations.

~part zip koru_std/control.zip.kz

Koru Standard Library: the `zip` part of control.kz. Joined via `~part zip` in control.kz; merged into the control module at load. The tor's declaration lives here too — the whole construct is one file (control.kz's line budget leaves no room for a second producer's declaration prose). `zip` walks TWO iterables in lockstep and delivers each aligned pair as a `{ first, second }` record through `! each` — a second producer, not a `for` axis (a `for` call is one traversal of one iterable; the axis refusal pins that). Each side is classified independently: a `lo..hi` range walks by arithmetic, anything else indexes by position, so `zip(0..5, names)` mixes the two freely. The walk stops at the shorter input; `| done n` delivers the pair count so the unpaired tail is an audible number. `step:` strides the pair index — `step: 2` delivers elements 0, 2, 4 of each side. The `! each` payload is `*`-wildcard like `for`'s: the pair is a record, and its field vocabulary is fixed by the emitted literal — `first` (element of `a`), `second` (element of `b`).

~part capture-preamble koru_std/control.capture-preamble.kz

Koru Standard Library: the `capture-preamble` part of control.kz. Joined via `~part capture-preamble` in control.kz; merged into the control module at load. Parts compile in their own scope — `struct_literal` is imported here, not inherited from the parent's file. This is the one region of the capture transform that cannot be target-neutral: a capture cell is a mutable named-field record plus a binding, and each host spells that differently. `cellPreamble` returns the whole host-side declaration text for the cell — seed literal and preamble line both — read `host_is_*` once in the caller, spell here.

~part capture koru_std/control.capture.kz

Koru Standard Library: the `capture` part of control.kz. Joined via `~part capture` in control.kz; merged into the control module at load. The cell-declaration spellings (host preamble + seed literal — the one part of the transform that cannot be target-neutral) live in control.capture-preamble.kz — parts are flat, so `~part capture-preamble` is declared in control.kz and the file lands beside this one. CAPTURE - Accumulation with pure semantics (ZERO OVERHEAD) Syntax: capture { total: 0 } ! as acc |> for(items) ! each i |> captured { total: acc.total + i } | captured final |> result(sum: final.total) Both `capture` and `captured` take a SOURCE BLOCK — bare braces, no parens. Bare `name { ... }` is unambiguously an invocation since the `=>` construct glyph took over branch construction (210_047). The parens forms `capture({...})` / `captured({...})` are retired (ratified 2026-06-11). A block holding a single bare expression (`capture { entity }`) seeds from an existing value instead of building a new struct cell. ARCHITECTURE: - capture is a comptime transform: `! as` binds the cell (live/during), `captured { ... }` invocations are rewritten into general `.assignment` nodes, `| captured` is the one-shot after-read. SEMANTICS: - Pure from Koru's perspective (captured computes the NEXT value) - Efficient mutation in generated Zig (var cell + field writes) - Decomposes fold while preserving purity guarantees The tor declares the USER surface (second [transform]proc migrant after std/regex:match): a source block, the `! as` cell effect, the optional `| captured` after-read. The shape checker enforces this contract with zero capture-specific code. The machine interface (invocation/item/program/ allocator → transformed SiteResult) is the proc-return convention.

capture

keywordcomptimetransform koru_std/control.capture.kz:38