Control Structures

Control Structures define how a sequence of expressions is evaluated

  • A ["Block"] expression defines a sequential control structure
  • An ["If"] expression defines a conditional control structure.
  • A ["FixedPoint"], ["Loop"], ["Sum"] or ["Product"] expression defines an iterative control structure.

Block and If

FunctionOperation
Block

[“Block”, expr-1, …expr-n]
[“Block”, dictionary, expr1, …expr-n]

The evaluation of a ["Block"] expression follows these steps:

  1. Create a new scope

  2. Set the value of the symbols in _dictionary_ in this scope.

    The dictionary argument can be a ["Dictionary"] expression, a ["KeyValuePair"] expression, a ["Pair"] expression or a ["Tuple"] expression.

  3. Evaluate each expr sequentially.

    If the value of an expression 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.

    Otherwise, the value of the ["Block"] expression is the value of the last expression

["Block", ["Tuple", "c", 5], ["Multiply", "c", 2]]
// ➔ 10
If

[“If”, condition, expr-1]

  • If the value of _condition_ is the symbol True, the value of the ["If"] expression is _expr-1_, otherwise Nothing.

[“If”, condition, expr-1, expr-2]

  • If the value of _condition_ is the symbol True, the value of the ["If"] expression is _expr-1_, otherwise _expr-2_.
["Value", "n", -10]
["If", ["Greater", "n", 0], "n", ["Negate", "n"]]
// ➔ 10

Loops

The Fold, Loop, Sum and Product functions are iteration control structures that share a similar form.

Their first argument, body is an expression that gets evaluated repeatedly. The body expression is evaluated with an implicit argument _ whose value is the current iteration element.

Their second argument, iterator can take the following shapes:

  • ["List", _expr-1_, ..._expr-n]: the _ implicit argument takes in turn each element
  • ["Range", _upper_]: the _ implicit argument is assigned the value 1, then incremented by 1 until it reaches at least upper.
  • ["Range", _lower_, _upper_]: the _ implicit argument is assigned the values from the lower bound to the upper bound of the range, with a step of 1.
  • ["Range", _lower_, _upper_, _step_]: the _ implicit argument is assigned the value lower then incremented by step until it reaches at least upper.

To use a named argument, use a ["Function"] expression for the body.

["Loop", ["Print", ["Square", "_"]], ["Range", 5]]
// ➔ 1 4 9 16 25
["Loop", ["Function", "x", ["Print", ["Square", "x"]]], ["Range", 5]]
// ➔ 1 4 9 16 25
FunctionOperation
FixedPoint

[“FixedPoint”, body, initial-value]
[“FixedPoint”, body, initial-value, max-iterations]

Assumes _body_ is an expression using an implicit argument _.

Apply _body_ to _initial-value_, then apply _body_ to 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 Same.

Inside _body_, use ["Break"] to exit the loop immediately or ["Continue"] to skip to the next iteration.

Fold

[“Fold”, body, iterator]
[“Fold”, body, initial-value, iterator]

Evaluate to [_body_, [_body_, _initial-value_, _elem-1_], _elem-2]]... where elem-1 and elem-2 are the first two elements from the iterator.

["Fold", "Multiply", ["List", 5, 7, 11]]
// ➔ 385

See above for the definition of iterator.

Loop

[“Loop”, body]
[“Loop”, body, iterator]

Repeatedly evaluate _body_ until the last element of the iterator is reached.

See above for the definition of iterator.

To exit the loop early, body should evaluate to a ["Break"] expression, a ["Continue"] expression or a ["Return"] expression.

["Loop", ["Print", ["Square", "_"]], ["Range", 5]]
// ➔ 1 4 9 16 25
["Loop", ["Function", "x", ["Print", ["Square", "x"]]], ["Range", 5]]
// ➔ 1 4 9 16 25
Product

[“Product”, iterator]

Evaluate to a product of all the elements in _iterator_. If all the elements are numbers, the result is a number. Otherwise it is a simplified list.

Equivalent to ["Fold", "Multiply", _iterator_].

["Product", ["List", 5, 7, 11]]
// ➔ 385
["Product", ["List", 5, "x", 11]]
// ➔ ["List", 55, "x"]

[“Product”, body, iterator]

Evaluate _body_ and make a product of the result.

Equivalent to ["Fold", ["Multiply", _1, [_body_, _2]], _iterator_].

See above for the definition of iterator.

Sum

[“Sum”, iterator]

Evaluate to a sum of all the elements in _iterator_. If all the elements are numbers, the result is a number. Otherwise it is a simplified list.

Equivalent to ["Fold", "Add", _iterator_].

["Sum", ["List", 5, 7, 11]]
// ➔ 23
["Sum", ["List", 5, "x", 11]]
// ➔ ["List", 16, "x"]

[“Sum”, body, iterator]

Evaluate _body_ and make a sum of the result.

Equivalent to ["Fold", ["Add", _1, [_body_, _2]], _iterator_].

Break and Continue

To control the flow of a loop expression, use ["Break"] and ["Continue"].

FunctionOperation
Break

[“Break”]
[“Break”, expr]

When in a block, exit the block immediately. The value of the ["Block"] expression is the ["Break"] expression.

When in a loop exit the loop immediately. The final value of the loop is _expr_ or Nothing if not provided.

Continue

[“Continue”]
[“Continue”, expr]

When in a loop, skip to the next iteration of the loop. The value of the iteration is _expr_ or Nothing if not provided.

When in a block, exit the block immediately, and return the ["Continue"] expression as the value of the block.