DEV Community

flisk
flisk

Posted on

Goose Functions: One Return, Two Returns, a Default

Part 2 of Goose, then any language on Flisk. Still no Docker. Run each file with goose file.goose.

Functions are free functions. There is no impl and no method table. xs.total() is exactly total(xs).

One return

total.goose:

fn total(xs: i64[:]) -> i64 {
    var t = 0;
    for x in xs { t += x; }
    return t;
}

fn main() {
    let nums: i64[] =;[10][12][20]
    print(total(nums));
    print(nums.total());
}
Enter fullscreen mode Exit fullscreen mode

i64[:] is a slice: a reference plus a count. The function does not copy the elements. let cannot be reassigned. var can. A block's value is its last expression, so a short function can omit return:

fn limit(x: i64, lo: i64 = 0, hi: i64 = 100) -> i64 {
    if x < lo { lo } else if x > hi { hi } else { x }
}
Enter fullscreen mode Exit fullscreen mode

A default is evaluated at each call that leaves it out. It may name globals and other functions. It may not name the caller's locals.

fn main() {
    print(limit(250));
    print(limit(-5, -10));
}
Enter fullscreen mode Exit fullscreen mode

That prints 100 and then -5.

Two returns, not a tuple

There is no tuple type. Several return values are a calling convention. The usual trailing bool means "the other value is meaningful."

divide.goose:

fn divide(a: i64, b: i64) -> i64, bool {
    if b == 0 { return 0, false; }
    return a / b, true;
}

fn main() {
    let q, ok = divide(7, 2);
    print(q, " ", ok);
    let bad, bad_ok = divide(7, 0);
    print(bad, " ", bad_ok);
}
Enter fullscreen mode Exit fullscreen mode

q, ok = divide(9, 3); writes into variables that already exist. A branch cannot end in 1, 2. Each branch returns on its own, as divide does.

if is an expression

fn label(hp: i64) -> u8[:] {
    if hp > 50 { "healthy" } else { "hurt" }
}

fn main() {
    print(label(80));
    print(label(10));
}
Enter fullscreen mode Exit fullscreen mode

u8[:] is a view of bytes. A string literal is a const u8[:]. There is no string type.

match is an expression too:

fn level(hp: i64) -> u8[:] {
    match hp { 0 => "dead", 1..50 => "low", _ => "fine" }
}
Enter fullscreen mode Exit fullscreen mode

Three rules that hit inside a function

  • u8 + u8 is an 8-bit add. A narrower type widens implicitly. Narrowing needs as or as!. u32 + i32 does not compile until you pick a side.
  • % is Euclidean. -7 % 3 is 2, never negative. Integer / truncates toward zero, so -7 / 3 is -2.
  • count++ is a statement, not an expression. You cannot write print(count++).

Part 3 passes a grow-only array into total. That is the function you will keep.

Top comments (0)