Examples

Lists that nobody keeps

The whole of examples/words.zeno, and what zeno run prints for it.

words.zeno
# Lists that nobody keeps.
#
# A line arrives from a serial console: "set led 3 on". The program
# splits it into words, looks at them, and keeps only what it needs.
#
# Every list below that is not given a name belongs to the statement
# that makes it, and is freed when that statement is over. So nothing
# here needs a collector, and this builds with none:
#
#     zeno run examples/words.zeno
#     zeno build --no-collector --memory examples/words.zeno
#
# docs/temporaries.md walks through it.

owned class Command {
    name: str
    args: owned list[str]

    function shown(self) -> str {
        return f"{self.name}/{len(self.args)}"
    }
}

function is_number(word: str) -> bool {
    for ch in word {
        if ch not in "0123456789" { return false }
    }
    return len(word) > 0
}

function not_empty(word: str) -> bool { return len(word) > 0 }

function loud(word: str) -> str { return word.upper() }

function count(items: borrow list[str]) -> int { return len(items) }

# `split` makes a list and `filter` makes another. The first belongs to
# the `return` statement, which frees it. The second is given back to
# the caller, who owns it from then on.
function words(line: str) -> owned list[str] {
    return line.split(" ").filter(not_empty)
}

function parse(line: str) -> Command raises ValueError {
    let parts = words(line)
    if len(parts) == 0 { raise ValueError("an empty line") }
    return Command(parts[0], parts.filter(is_number))
}

let line = "set  led 3 on 250"

# Looked at and gone: each of these lists lives for one statement.
print(count(line.split()))
print(len(words(line)))
print("led" in line.split())

# A loop walks the list it is given, and frees it after the last trip.
for word in words(line).map(loud) {
    print(word)
}

# Kept: these lists have owners.
let numbers: owned list[str] = words(line).filter(is_number)
var history: owned list[str] = []
history += words(line)
history += ["end"]
print(numbers)
print(history)

for text in [line, "", "stop now"] {
    try {
        let command = parse(text)
        print(command.shown())
    } except ValueError as e {
        print("refused:", e.message)
    }
}
zeno run examples/words.zeno
5
5
true
SET
LED
3
ON
250
["3", "250"]
["set", "led", "3", "on", "250", "end"]
set/2
refused: an empty line
stop/0

See it on GitHub: examples/words.zeno.