Skip to content

The book · 02

Functions and flow

book.md · 96 lines · 2 min read

Goal: write functions, understand why nothing is returned by position, and use the two unified control constructs: match and loop.

fn add(a: int, b: int) -> int {
return a + b
}
fn saudar(nome: string) { // no '->': returns no value (there is no 'void')
io.println("hi, {{nome}}")
}
pub fn dobro(x: int) -> int { return x * 2 } // 'pub' = visible to other modules

Parameters with defaults and variadics:

fn conectar(host: string, porta: u16 = 8080) { ... } // 'porta' has a default
fn somar(xs: ...int) -> int { ... } // variadic: '...' prefix

A block is not worth its last expression. Every output is marked explicitly: by return, by the ternary’s ?:, or by a lambda’s =>. What is forbidden is delivering by position (“the last line is the value”). Marking with a short glyph counts as explicit; you just don’t guess.

fn maior(a: int, b: int) -> int {
return a > b ? a : b // ternary: a choice between TWO values
}

return distributes over match/if in value position:

fn classificar(n: int) -> string {
return match { // 'return <match>' distributes the return across the arms
n < 0 => "negative"
n == 0 => "zero"
_ => "positive"
}
}

A single construct for “given X, choose one branch”, which absorbs switch, classic match, and select. The token right after match decides the form:

// with a subject → matches patterns / values
match status {
200 | 201 | 204 => ok() // or-pattern with '|' (covers the fallthrough)
404 => sumiu()
_ => outro() // open domain (int) → requires '_'
}

Exhaustiveness is taken seriously: in a closed domain (enum, error-set) the compiler requires all arms and forbids _. Adding a variant breaks the build until you handle it. In an open domain (int, string) the _ is mandatory.

(The match { ... } form without a subject is the channel select, in chapter 06.)

for, while, and infinite loop differ only in the header, so there is one keyword, loop:

loop { break } // no header → infinite
loop ativo { ... } // boolean expression → while
loop item in lista { ... } // IDENT in iterable → for-each
loop i in 0..8 { ... } // exclusive range (..= is inclusive)
loop i := 0; i < 8; i = i + 1 { } // C-style; ';' delimits the 3 parts

break and continue work the same in all forms.

An anonymous function passed inline. Two forms, both only in argument position (it does not bind to a name; to reuse, give it a name with fn):

nums.filter(fn(x) => x > 0) // short form: '=>' delivers the value
nums.map(fn(x) { y := x * 2; return y }) // body form: explicit 'return'

Next: 03 · Composite types