Control Structures
Control Structures define how a sequence of expressions is evaluated.
Overview
The flow of a program is controlled by control structures. Control structures are expressions that define how a sequence of expressions is evaluated.
There are three kind of control structures:
- Sequential:
Block, the most common where expressions are evaluated one after the other - Conditional
IforWhich, where expressions are evaluated depending on the value of a condition - Iterative
LooporFixedPoint, where expressions are evaluated repeatedly
Sequential Control Structure
Block(expr-1, ...expr-n)
A ["Block"] expression is a sequence of expressions that are evaluated
sequentially.
A new scope is created for the ["Block"] expression. The scope is destroyed
when the ["Block"] expression is finished evaluating. This means that
variables defined in the ["Block"] expression are not accessible outside of
the ["Block"] expression.
The value of the ["Block"] expression is the value of the last expression
expr-n.
If one of the expression in the block is a ["Return"] expression, a
["Break"] expression or a ["Continue"] expression, no more expressions are
evaluated and the value of the ["Block"] is this expression.
["Block"] expressions can be nested as necessary.
["Block", ["Assign", "c", 5], ["Multiply", "c", 2]]
// ➔ 10
Conditional Control Structure
If(condition, expr-1)
If the value of conditionis the symbol True, the value of the ["If"]
expression is expr-1, otherwise Nothing.
If(condition, expr-1, expr-2)
If the value of conditionis the symbol True, the value of the ["If"]
expression is expr-1, otherwise expr-2.
Here's an example of a function that returns the absoluve value of a number:
["Function", ["If", ["Greater", "n", 0], "n", ["Negate", "n"]], "n"]
["If"] expressions can be nested as necessary.
Which(condition-1, expr-1, ...condition-n, expr-n)
The value of the ["Which"] expression is the value of the first expression
expr-n for which the corresponding condition condition-n is True.
["Block",
["Assign", "n", -10]
["Which", ["Greater", "n", 0], "n", ["Negate", "n"], "n"]
]
// ➔ 10
A ["Which"] expression is equivalent to the following ["If"] expression:
["If", ["Equal", condition-1, "True"], expr-1,
["If", ["Equal", condition-2, "True"], _expr-2,
... ["If", ["Equal", condition-n, "True"],
expr-n,
"Nothing"
]
]
]
A ["Which"] expression is equivalent to a switch statement in JavaScript or
the Which[] function in Mathematica.
Loops
Loop(body)
Repeatedly evaluate bodyuntil the value of bodyis a ["Break"] expression,
or a ["Return"] expression.
["Break"]exits the loop immediately. The value of the["Loop"]expression is the value of the["Break"]expression.["Return"]exits the loop and returns the value of the["Return"]expression.
To exit the loop, a ["Break"] or ["Return"] expression must be evaluated.
Loop with only a body argument is equivalent to a while(true) in
JavaScript or a While[True, ...] in Mathematica.
Loop(body, collection)
Iterates over the elements of collection and evaluates body with an implicit
argument _ whose value is the current element. The value of the ["Loop"]
expression is the value of the last iteration of the loop, or the value of the
["Break"] expression if the loop was exited with a ["Break"] expression.
["Loop", ["Print", ["Square", "_"]], ["Range", 5]]
// ➔ 1 4 9 16 25
["Loop", ["Function", ["Print", ["Square", "x"], "x"]], ["Range", 5]]
// ➔ 1 4 9 16 25
Loop with a body and collection to iterate is equivalent to a forEach()
in JavaScript. It is somewhat similar to a Do[...] in Mathematica.
FixedPoint(body, initial-value)
FixedPoint(body, initial-value, max-iterations)
Assumes bodyis an expression using an implicit argument _.
Apply bodyto initial-value, then apply bodyto the result until the result
no longer changes.
To determine if a fixed point has been reached and the loop should terminate,
the previous and current values are compared with Equal.
Inside body, use a ["Break"] expression to exit the loop immediately or
Return to exit the enclosing ["Function"] expression.
Controlling the Flow of Execution
To exit a function, use Return.
To control the flow of a loop expression, use Break and Continue.
Return(value)
Interupts the evaluation of a ["Function"] expression. The value of the
["Function"] expression is value.
The ["Return"] expression is useful when used with functions that have
multiple exit points, conditional logic, loops, etc...
Here's a contrived example of a function that returns the sign of a number:
[
"Function",
[
"Block",
["If", ["Greater", "x", 0], ["Return", 1]],
["If", ["Less", "x", 0], ["Return", -1]],
0
],
"x"
]
Break()
Break(value)
When in a loop exit the loop immediately. The final value of the loop is
valueor Nothing if not provided.
Continue()
Continue(value)
When in a loop, skip to the next iteration of the loop. The value of the
iteration is value or Nothing if not provided.