Blocks
A block is a first-class callable code value (Types):
every brace-delimited form { … } is a block. A block's body is a
newline/semicolon-separated sequence of statements. A block bound to a
name — by def, or as a builtin — is a function.
Block = '{' [ ParamList ] Body '}' .
Body = { Statement (newline | ';') } .
Statement = CommandCall . # see Expressions
ParamList = '<' { param } [ '...' param ] '>' .
Control-flow constructs, handlers, and ordinary callables all receive the same kind of value — a block — and differ only in how they invoke it (Expressions, Program initialization and execution).
Named-parameter blocks
{ <params> body } — one or more parameter names inside angle brackets,
immediately after {. The parameters bind the arguments positionally; the
body reads them by name.
{ <x> + $x 1 }
{ <x y> + $x $y }
{ <drink> do "say one $drink" }
Whitespace and newlines inside <...> and between > and the body are
insignificant. The idiom for a long body is to put the signature on the
opening line:
def calculate_damage { <attacker weapon target>
...body...
}
Rest parameter
The final parameter may be prefixed with ..., making the block
variadic. The rest parameter binds an iterable over the trailing
arguments (iterables) — the arguments beyond the
declared parameters, in call order, each preserved as a distinct element.
Only one rest parameter is allowed and it must be last.
{ <first ...others> ... } # first arg named; the rest as an iterable
{ <...all> ... } # fully variadic, zero or more args
The rest iterable is heterogeneous (an element may be of any type) and
order-preserving. Because each argument is one element, it is not a word
iterable: an argument whose value contains spaces stays a single element.
(Contrast $args, the whitespace-split command line, which is a word
iterable —
Program initialization and execution.)
Being an ordinary iterable, it is consumed by the iterable consumers
(Built-in functions) and may be traversed more
than once. When the call passes no trailing arguments the rest parameter
binds an empty iterable, never null: [count $rest] is 0.
Restrictions
- A parameter name must be a bareword. An integer or boolean literal
(
<5>,<true>) is reserved and is not a valid parameter name (Lexical elements). - Parameter names must be distinct; a duplicate (including
<a ...a>) is a compile-time error.
Arity and calls
Declared arity is the number of non-rest parameters and is a strict
minimum. A call with fewer arguments is a run-time error. Extra
arguments are dropped (non-variadic) or collected into the rest iterable
(variadic). Arguments bind to the parameters positionally; a
parameter-less { body } ignores any arguments it is called with.
The caller decides how many arguments a block receives: some callers
pass zero (e.g. if branches), others pass one per element (e.g.
each). The individual callers are documented in
Expressions and
Built-in functions. Handler argument binding is specified in
Program initialization and execution.
Compile-time arity check for zero-argument consumers
if and randomly invoke their branch blocks with zero arguments. A
branch that is a block with declared arity ≥ 1 can never be satisfied,
so it is rejected at compile time. The empty forms { <> body }, a
pure rest { <...rest> body }, and a plain { body } accept zero
arguments and are allowed.
Block value and return
A block's value is the value of its body's last evaluated statement, returned when control falls off the end.
{ <x> + $x 1 } # returns x + 1
{ do "wave" } # returns the result of the last statement
Special cases:
- An empty body —
{},{ <> },{ <x> }with no statements — returnsnull. return valueexits the block early withvalue; barereturnreturnsnull.
break, continue, and return propagate outward through enclosing
constructs; the full rules are in Run-time.
Statement form
Every statement is a command call (Expressions) and produces a value; the body discards all but the last.