Blocks
A block is a piece of code you can pass around and call later. Every
brace-delimited { … } is a block. Blocks are what control-flow forms
like if run, what consumers like each
and select invoke per element, and what a
def binds to a name.
A block's body is a sequence of statements separated by newlines or semicolons. Each statement is a command call.
{ do "wave" }
{ do "smile" ; do "bow" }
Parameters
When a block needs arguments, declare the parameter names in angle brackets immediately after the opening brace. The parameters bind the arguments by position, and the body reads them by name.
- RIGHT:
each [creatures $self] { <c> do "smile $c" } - WRONG:
each [creatures $self] <c> { ... }← compile error
{ <x> [+ $x 1] } # one parameter
{ <x y> [+ $x $y] } # two parameters
{ <drink> do "say one $drink" }
Whitespace and newlines inside <...> and between > and the body do not
matter. For a long body, the idiom is to put the signature on the opening
line:
def calculate_damage { <attacker weapon target>
...body...
}
Parameter names must be plain words (not <5> or <true>, which are
reserved literals) and must be distinct.
The rest parameter ...
The last parameter may be prefixed with ..., making the block accept any
number of trailing arguments. The rest name binds an
iterable over those extra arguments, in call order, each
kept as a separate element.
{ <first ...others> ... } # first named; the rest as an iterable
{ <...all> ... } # zero or more args, all collected
Only one rest parameter is allowed and it must come last. Because each
argument is one element, the rest iterable is not a word iterable: an
argument that contains spaces stays a single element. (Contrast
$args, the whitespace-split command
line.) When no extra arguments are passed, the rest binds an empty
iterable, never null — [count $rest] is 0.
How many arguments
The declared parameters are a strict minimum: calling a block with fewer
arguments is a run-time error. Extra arguments are dropped (or collected by
a rest parameter). A parameter-less { body } ignores any arguments it is
given. The caller decides how many arguments to pass —
if passes none, each passes one per
element — so a block handed to if may not declare a required parameter.
Returned values
By default, a block will return the value of the last statement that
executes. Because every statement is a command call, that last
statement must itself be a value-producing call — a [...]
substitution or a query command — for the block to yield a useful
value:
def inc { <x> [+ $x 1] } # yields x + 1
To return a value early, or to make the intent explicit, use
return:
def classify { <c>
if [ge [level $c] 20] { return [upper "elite"] }
return [upper "common"]
}
A plain variable or literal alone is not a value statement — a line that
is just $n or 'elite' is read as a command call and fails. Wrap it:
write return $n, or [upper "elite"], rather than a bare $n.
An empty body — {}, { <> }, or { <x> } with no statements — yields
null, and so does bare return.
Examples
after command (say) {
each [words "north east south west"] { <dir>
do "say I could go $dir."
}
}
Runs the one-parameter block once per word.
def inc { <x> [+ $x 1] }
after command (say) {
do "say [inc 4]"
}
A named block used as a function; [inc 4] yields 5, so the mob says
"5."