← All examples

Gradebook

gradebook.zg
pub const 'passing' := 60;

struct Student {
    name: str.utf8,
    scores: list[int32]
}

fn average [lent 's': Student] -> int32 or fail[no_scores] {
    if list.length[lend 's'.scores] equal_to 0 { fail no_scores; }
    let 'total' := 0;
    for 'x' in lend 's'.scores { change 'total' = 'total' plus 'x'; }
    check return 'total' div.floor list.length[lend 's'.scores];     # the if above proves the divisor is not 0
}

fn record [lent.mut 's': Student, 'score': int32] -> fail[out_of_range: int32] {
    if 'score' < 0 or 'score' > 100 { fail out_of_range['score']; }
    list.append[lend.mut 's'.scores, value 'score'];
}

fn grade [lent 's': Student] -> str.utf8 {
    let 'avg' := average[lend 's'] otherwise return to.stored.str.utf8['passing'] ++ "? no scores";
    if 'avg' at_least 'passing' { return "pass (" ++ to.stored.str.utf8['avg'] ++ ")"; }
    return "fail (" ++ to.stored.str.utf8['avg'] ++ ")";
}

MAIN {
    let 'a' := Student[name = "Ann", scores = list.empty];
    let 'b' := Student[name = "Bo", scores = [40, 55]];
    let 'marks' := [72, 130, 88];

    for 'm' in lend 'marks' {
        record[lend.mut 'a', 'm'] otherwise {
            out_of_range 'bad' { std::print.useful["skipping ", 'bad', newln]; }
        };
    }
    record[lend.mut 'b', 65] otherwise std::exit[1];

    let 'students' := [give 'a', give 'b', Student[name = "Cy", scores = list.empty]];
    let 'passed' := 0;
    for 's' in lend 'students' {
        std::print.stored['s'.name, ": ", grade[lend 's'], newln];
        let 'avg' := average[lend 's'] otherwise 0;
        if 'avg' at_least 'passing' { change 'passed' = 'passed' plus 1; }
    }
    std::print.useful['passed', " of ", list.length[lend 'students'], " passed", newln];
}
Output
skipping 130
Ann: pass (80)
Bo: fail (53)
Cy: 60? no scores
1 of 3 passed