Docs/Language fundamentals

Control flow

Choose a branch, repeat work, and return a value from a decision.

On this page

Use if for conditions, while to repeat while a condition holds, and each to visit a collection. Conditions have type bool.

Choose between branches#

Valk
fn describe(score: int) String {
    if score >= 80 {
        return "Excellent"
    } else if score >= 50 {
        return "Passed"
    } else {
        return "Try again"
    }
}

fn main() {
    println(describe(72))
}

For a single statement, a colon can replace a block: if score < 0 : return. Use braces when the branch contains multiple steps.

Repeat with while#

Valk
fn main() {
    let remaining = 3
    while remaining > 0 {
        println(remaining)
        remaining--
    }
}

The condition is checked before each iteration, so a loop can run zero times. break leaves a loop, and continue skips to its next iteration.

Visit collection elements#

Valk
fn main() {
    let tasks = Array[String]{ "Build", "Test", "Ship" }
    each tasks as task, index {
        println("%{index + 1}. %task")
    }
}

An array yields its value and, optionally, its index. A map yields its value, then its key, then an optional iteration index. These orders are useful to remember when moving between the two collection types.

Match a set of alternatives#

Use match when a value has a known set of cases. A match can itself produce a value:

Valk
enum Status { queued running finished }

fn label(status: Status) String {
    return match status : String {
        Status.queued => "Waiting"
        Status.running => "In progress"
        Status.finished => "Done"
    }
}

fn main() {
    println(label(Status.running))
}

The : String declares the result type of the match. Every branch must produce that type or leave the surrounding flow, for example with return or throw. Handling every enum item makes this match exhaustive. Use a default case when the set of values is open-ended.

Tagged unions also work with match, and let each case carry a different kind of value.

Compute a value in a block#

A value scope, written <{ ... }, groups several steps into one expression. Its return supplies the expression's result:

Valk
fn main() {
    let total = <{
        let subtotal = 40
        let delivery = 5
        return subtotal + delivery
    }
    println(total)
}

This is useful when a fallback needs more than a literal, such as logging an error before returning a default.