The loop functions and Step: repeat a function while a condition holds, across a range of integers, or until it returns #Done.
Answers the State the loop settles on, or the answer a step stops with.
A startingWith value seeds the State and a body advances it. The entries differ in what ends the loop. The while and until entries check a predicate before each step. The counted entries run over a range of Integers. A positional body runs the loop to its end. A step body answers with a Step and can stop the loop early. Pick the entry by the labels it reads, as with an overloaded Method.
9 entries. A call picks one by the labels it writes.
Modes
StepWhat a callback answers to say whether a loop goes round again.
Predicate loops
while
loop<infer State>( startingWith state: State, while condition: (_: State) -> Boolean, _ advance: (_: State) -> State,) -> State
Answers the first State the condition rejects.
The condition is checked before each step. A condition that is false on the seed answers the seed unchanged, and the loop runs zero times. This entry is one of the family's two natives.
NameTypeDescription
startingWithStatethe State the loop begins from.
while(_: State) -> Booleanthe condition, checked against the State before each step; the loop continues while it is true.
_(_: State) -> Statethe body, handed the running State and answering with the next.
loop<infer State>( from start: Integer, through end: Integer, startingWith state: State, _ advance: (_: Integer, _: State) -> State,) -> State
Runs the body once for each Integer from from up through through, and answers the State after the last step.
Both endpoints are included and the count only runs up. An end below the start runs the body zero times and answers the seed untouched. That mirrors List.of(integersFrom:through:). To count down, use the downTo: entry. The entry always finishes, because the range is fixed before the first step.
NameTypeDescription
fromIntegerthe first Integer the body sees.
throughIntegerthe last Integer the body sees, included.
startingWithStatethe State the first step builds on.
_(_: Integer, _: State) -> Statethe body, handed each Integer and the running State, answering with the next State.
Returns the State after the last step, or the seed when the body never runs.
Example
constant total = loop(from 1, through 10, startingWith 0, (index, sum) { <- sum::add(index)})expect total::is(55)constant backwards = loop(from 3, through 1, startingWith "none", (index, text) { <- "{text}{index}"})expect backwards::is("none")
Runs the body once for each Integer from from up to, but not including, upTo, and answers the State after the last step.
The count only runs up. The body runs zero times when upTo is not above from, and the seed is answered untouched. That mirrors List.of(integersFrom:upTo:), so a count written from a length is empty rather than inverted.
NameTypeDescription
fromIntegerthe first Integer the body sees.
upToIntegerthe Integer the count stops before.
startingWithStatethe State the first step builds on.
_(_: Integer, _: State) -> Statethe body, handed each Integer and the running State, answering with the next State.
Returns the State after the last step, or the seed when the body never runs.
Runs the body once for each Integer from from down through downTo, and answers the State after the last step.
Both endpoints are included and the count only runs down. The first Integer is always seen, so an end above the start runs the body once. That mirrors List.of(integersFrom:downTo:). The entry always finishes, because the range is fixed before the first step.
NameTypeDescription
fromIntegerthe first Integer the body sees.
downToIntegerthe last Integer the body sees, included.
startingWithStatethe State the first step builds on.
_(_: Integer, _: State) -> Statethe body, handed each Integer and the running State, answering with the next State.
Each step answers with a Step. A #Continue carries the next State, and the loop goes again. A #Done carries the answer, and the loop finishes with it. This entry ends on a decision the State makes, rather than on a count or a fixed predicate. It is the family's other native.
NameTypeDescription
startingWithStatethe State the loop begins from.
step(_: State) -> Step<State, Answer>the body, handed the running State and answering with a Step: #Continue to go again, #Done to stop.
Returns the value the first #Done carries.
Example
constant answer = loop(startingWith 1, step (n) { if n::isGreaterThan(50) { <- #Done("the first power of two over 50 is {n}") } <- #Continue(n::multiply(with 2))})expect answer::is("the first power of two over 50 is 64")
through-step
loop<infer State>( from start: Integer, through end: Integer, startingWith state: State, step advance: (_: Integer, _: State) -> Step<State, State>,) -> State
Runs the body over the Integers from from up through through, and lets the body stop before the end.
Each step answers with a Step. A #Continue carries the next State, and the count goes on. A #Done carries the answer, and the loop finishes with it at once. The count running out answers the State the last step carried. An end below the start runs the body zero times and answers the seed.
NameTypeDescription
fromIntegerthe first Integer the body sees.
throughIntegerthe last Integer the body sees, included.
startingWithStatethe State the first step builds on.
step(_: Integer, _: State) -> Step<State, State>the body, handed each Integer and the running State, answering with a Step.
Returns the State the count ran out on, or the value the first #Done carries.
Example
constant firstOverTen = loop( from 1, through 100, startingWith 0, step (index, total) { constant next = total::add(index) if next::isGreaterThan(10) { <- #Done(next) } <- #Continue(next) },)expect firstOverTen::is(15)
Runs the body over the Integers from from up to, but not including, upTo, and lets the body stop before the end.
Each step answers with a Step, as the through: entry beside it reads. The body runs zero times when upTo is not above from, and the seed is answered untouched.
NameTypeDescription
fromIntegerthe first Integer the body sees.
upToIntegerthe Integer the count stops before.
startingWithStatethe State the first step builds on.
step(_: Integer, _: State) -> Step<State, State>the body, handed each Integer and the running State, answering with a Step.
Returns the State the count ran out on, or the value the first #Done carries.
Runs the body over the Integers from from down through downTo, and lets the body stop before the end.
Each step answers with a Step, as the through: entry reads. The first Integer is always seen, so an end above the start runs the body once and answers what that step carried.
NameTypeDescription
fromIntegerthe first Integer the body sees.
downToIntegerthe last Integer the body sees, included.
startingWithStatethe State the first step builds on.
step(_: Integer, _: State) -> Step<State, State>the body, handed each Integer and the running State, answering with a Step.
Returns the State the count ran out on, or the value the first #Done carries.
What a callback answers to say whether a loop goes round again.
#Continue carries the next State, and #Done carries the answer the loop finishes with. A match checks the two Cases like any other Choice.
State is what a loop threads from turn to turn, and Answer is what it finishes with. The two are independent. The step entries of loop and List::reduce's early-stopping entry both read one.
Cases#Continue { state: State }, #Done { value: Answer }