"For" and "with" expressions
"For" loops
The for
syntax is designed for iterating over collections.
It can be void
as above,
or it can be used to map over a collection.
It can even produce a different type of collection.
It can be written on one line by using a ;
.
Desugaring for loops
for
is actually just syntax for calling a function
for-loop
and passing it a lambda.
(That is usually implemented using a loop
or by delegating to another for-loop
function.)
"For-break" loops
Sometimes you want to stop the loop early.
For that, use break
and continue
like in a loop
.
This desugars to calling a function
for-break nat(xs nat[], f-body nat break-or-continue mut(x nat), f-else nat mut())
.
The break
and continue
keywords
desugar into constructing break-or-continue
values.
That type is declared in misc.
Like in a loop
, break
can take a value.
Since the break
isn't guaranteed to be reached
(since the collection could run out first), the result is wrapped in an option.
You could avoid that by providing an else
block to provide a value
if break
isn't reached.
The above calls a function that works like
for-break nat(xs nat[], f-body nat break-or-continue mut(x nat), f-else nat mut())
.
"With" expressions
A related expression is with
.
Technically, this behaves exactly like for
except that the function it calls is named with-block
instead of for-loop
.
However, using with
instead of for
implies that the body will usually execute only once.
It's not meant for loops.
One example use is to build a collection.
build
returns a type called build-options
which is used as the argument to with-block
.
The signature works like with-block string(a build-options, f void mut(out string-builder))
.