Slide 33 of 74

func and proc

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.