proc grow(vec: mut Str[dyn], tag: Str): void {
append(vec, tag)
}
// A func may call a proc — on storage of its own.
func tagged(base: Str[], tag: Str): Str[dyn] {
mut Str[dyn] out = []
for each b in base {
append(out, b)
}
grow(out, tag)
return out
}
proc main(): void {
mut Str[dyn] tags = ["bee"]
echo tagged(tags, "hive") // ["bee", "hive"]
echo tags // ["bee"] — the func changed nothing of ours
grow(tags, "wax")
echo tags // ["bee", "wax"] — the proc did
}Both may do anything a program does — echo, files, the network, starting threads — and both may call either. They differ in one thing: a func cannot declare a mut parameter, so it can never write to storage its caller can see. It may still call a proc, because a mut parameter has to be handed a mut variable and the only ones inside a func are its own. A mut variable passed to a func arrives as an immutable copy.
So a func is a promise a reader can lean on — calling it changes nothing of yours — and a proc is where writing through the caller's storage is allowed. Programs start at a proc, main. How a call runs, waited for or on a thread of its own, is decided where it is called, never where it is declared.