105 Control Flow


var Integer total = 0;

for Integer n in 1..100 {
    total += n;
}

print total;

This program prints 5050. The declaration creates an exactly-one Integer location named total. The range expression 1..100 denotes the finite extension containing the integers from 1 to 100 inclusive. The for statement executes the body once for each member of that extension, binding n to one integer at a time. The statement total += n; is a local program-state update.


var Integer total = 0;
var Integer n = 1;

while n ≤ 100 {
    total += n;
    n++;
}

print total;

The while form is useful when the next iteration depends on state changed by the body. Its condition must have element type Boolean and cardinality one. In strict mode this is checked statically. In dynamic mode a condition that does not produce exactly one Boolean value raises a runtime exception.


if total = 5050 {
    print "ok";
} else {
    print "wrong", total;
}

An if statement chooses between statement blocks. Its condition has the same requirements as a while condition: it must produce exactly one Boolean value. The expression form if C then A else B remains available when the program needs to choose a value inside a larger expression.

Integer Ranges

The expression A..B is an inclusive integer range. Both endpoints must have element type Integer and cardinality one. If A ≤ B, the range contains each integer from A to B inclusive. If A > B, the range is empty. The element type of the range is Integer; its cardinality may be many. This is the infix range form; the prefix form ..supplier[...] remains lookup notation inside literals.

Blocks and Scope

A block is a sequence of statements surrounded by braces. Variables declared inside a block are visible from their declaration to the end of that block, including nested blocks. They are not visible after the block has finished. Declaring a block variable with the same name as a visible block variable or loop binding is a static error.

Control-flow analysis also tracks the initialisation state of locations. A location may be read after a branch or loop only when it is definitely initialised on every reachable incoming path; see Uninitialised Locations.

The loop variable introduced by for is an exactly-one local binding scoped to the loop body. It is rebound for each iteration and cannot be used as an update target. The explicit type in for Integer n in 1..100 may be omitted when it can be inferred from the source expression.

Iteration Sources

A for source is an expression whose result may contain zero, one, or many members. The body executes once for each member. If the source is empty, the body does not execute.


var Integer total = 0;

for Integer qty in s.shipment.qty {
    total += qty;
}

This example adds quantities reached by a query path. Because addition is commutative, the result does not depend on iteration order. A numeric range has the natural ascending order of its integers. Other extensions are mathematical sets; unless an expression explicitly defines an order, a program must not rely on the order in which their members are visited.

Break and Continue


var Integer total = 0;
var Integer n = 0;

while true {
    n++;

    if n > 100 {
        break;
    }

    if n = 50 {
        continue;
    }

    total += n;
}

The statement break; exits the nearest enclosing loop. The statement continue; starts the next iteration of the nearest enclosing loop. Using either statement outside a loop is a static error.

Transactions

Control flow does not change the distinction between local program-state updates and database-state updates. A loop that updates only program variables does not require a transaction. A loop that writes persistent database locations requires an open transaction for the relevant data partition, just as the same database-state update would outside a loop.