<!-- https://epsil.dev/reference/control-structures/ -->

# Control structures

The 13 definitions of the control structures library, each with its Epsil spelling, its MathJSON name, its signature and its full description.

Each definition is listed under its Epsil spelling (the MathJSON name when
it has none), with its signature in the engine's type syntax. The
[Standard Library](/library/) page is the one-page index of every
category.

## Definitions

### Alternatives

`(expression+) -> nothing`

Inside a `Match` pattern, `Alternatives(p1, p2, …)` matches if any alternative matches. Alternatives must be binding-free.

### Break

`(value: any?) -> nothing`

Exit the enclosing loop immediately, optionally with a value (`Break(v)`) that becomes the loop value.

### Comprehension

`(body: expression, iterators: expression+) -> list`

Value-producing comprehension: evaluate `body` in nested iteration over one or more `Element` clauses and collect the results into a list. Later clauses see earlier bindings; independent clauses produce a Cartesian product. A clause with a third operand, `Element(x, xs, cond)`, is a guard: only the elements for which `cond` evaluates to `True` are visited.

### Condition

`(expression, symbol?) -> boolean`

Test whether a value satisfies one or more conditions.

### Continue

`() -> nothing`

Skip to the next iteration of the enclosing loop.

### fixedPoint

MathJSON `FixedPoint` · `(any) -> unknown`

Iterate a function until a fixed point is reached.

### If

`(expression, expression, expression?) -> any`

Conditional branch: evaluate one of two expressions.

### Loop

`(body: expression, iterators: expression*) -> any`

Imperative loop, evaluated **for effect**. `Loop(body)` repeatedly evaluates `body` until it yields a `Break` or `Return`. `Loop(body, Element(x, coll), …)` iterates `body` in nested iteration over the Element clauses (later clauses see earlier bindings; independent clauses produce a Cartesian product). The loop value is `Nothing`, or the value carried by a `Break`/`Return`. For a value-producing comprehension use `Comprehension` or `Map`.

### Match

`(expression, expression+) -> unknown`

Structural pattern match. `Match(subject, MatchCase(pattern, body), …)` evaluates `subject` once, then selects the first case whose pattern matches (structurally, `isSame`-like) and whose guard holds, applying its body to the captured values. Unlike `Which`, `Match` always decides: a symbolic subject that is not structurally a case still falls through to a wildcard case. No matching case yields `Error("match-no-case", subject)`.

### MatchCase

`(expression, expression, expression?) -> nothing`

A case of a `Match`: `MatchCase(pattern, body)` or `MatchCase(pattern, guard, body)`. The pattern holds engine wildcards; the body references the bound capture names.

### Pin

`(expression) -> nothing`

Inside a `Match` pattern, `Pin(expr)` matches the value of `expr` (evaluated at match time) rather than its structure.

### when

MathJSON `When` · `(expression, boolean) -> any`

Conditional/restriction value. `When(e, cond)` evaluates to:
  - `e` when `cond` evaluates to `True`
  - the absence marker of the type of `e` when `cond` evaluates to `False` (the "masking rule"): `NaN` for a number, `Missing` — the position-preserving absent datum, the answer a selection with no selected branch gives — for a point, a list, a string or a value not provably numeric; consumers like 2D plotters skip masked points
  - `When(e, cond_simplified)` when `cond` is indeterminate (holds)
Stacked restrictions canonicalize: `When(When(e, c1), c2)` → `When(e, And(c1, c2))`.
Compiles to ternary `(cond) ? (e) : NaN` in JS and GLSL.

### Which

`(expression+) -> unknown`

Return the value for the first condition that is true.
