 Previous Home Contents Next

# Chapter 5: Expressions

5.1 Names

5.2 Literals

5.3 Definitions

5.4 Assignments

5.5 Functions

5.6 Function Calls

5.7 Imperatives

5.8 Multiple Values

5.9 Sequences

5.10 Exits

5.11 If

5.12 Logical Expressions

5.13 Loops

5.14 Generators

5.15 Collections

5.16 General Branching

5.17 Never

Aldor is an expression-based language: every construct in the language produces zero, one or more values. This chapter describes the structure of expressions in Aldor and the rules for expression evaluation.

### 5.1 : Names

The evaluation of a name in Aldor causes the value of a variable or constant to be retrieved.

If a name refers to a variable or constant defined in the same scope or in an enclosing scope then retrieving its value is a very inexpensive operation. If a name refers to an imported constant, then there may be a cost associated with the look up, depending on the degree of optimization used to compile the program.

Consider the following example:

```#include "aldor"

f(n: SingleInteger): SingleInteger ==
if n < 2 then
1
else
n * f(n-1);
```

In the last line, the name "n" is defined in the current scope and the name "f" is defined in an enclosing scope, so their use is very inexpensive. The names "*", "-" and "1" are imported from `SingleInteger`. If this program is compiled with optimization, then there is no cost in using the values from `SingleInteger`. Without optimization, these values would have to be dynamically retrieved from `SingleInteger` at a modest cost.

A name may represent a variable, which may take on different values at different points in a computation, or a constant, which always refers to the same value every time it is used.

Names for constants may be overloaded in Aldor. That is, it is possible to have more than one constant with a given name, visible at the same point in a program. Names for variables cannot be overloaded. A name cannot represent both a variable and a constant in the same scope.

### 5.2 : Literals

Literal constants are expressions which represent the explicit data values which appear in a program. There are three styles of literal constants in Aldor: quoted strings, integers and floating-point numbers:

```"Aloha!"                    -- quoted string literal
10203040  16rFFFFC010       -- integer literals
1.234e56                    -- floating-point literal
```

The meaning of a constant in Aldor is determined by the environment in which it is used. For example, the constant 1.234e56 might be a value of type `SingleFloat`, `DoubleFloat` or `Float`, depending on the context.

When a literal expression is encountered in a program, it is treated as an application of a corresponding ``literal accepting'' operation:

```string:  Literal -> T
integer: Literal -> T
float:   Literal -> T
```

(where T represents the type of the value being formed).

Each of these operations takes a single argument of type `Literal` and constructs a value of the appropriate type. When programs are compiled against the base Aldor library, the constant-folding optimization will immediately convert constants of the following types to their machine representations: `String`, `SingleInteger`, `Integer`, `SingleFloat`, `DoubleFloat`.

New types may provide their own interpretation of literal constants by exporting a literal forming operation with the corresponding signature. As a consequence, if operations for creating string literals, for example, are available from several types, it may be necessary to provide a declaration to indicate which kind of literal is intended. When implementing literal-forming operations for new types, it is often useful to use the `string` literal-forming operation from `String`.

Some types may accept some literal values and not others. For example, a fixed-precision integer type might reject values which lie outside the range of values representable by the type.

String literals

String-style literals are enclosed in quotation marks. Inside a string-style literal, an underscore character "_" is used as an escape character to modify the meaning of the characters which follow:

• A quotation mark after an underscore includes a quotation mark in the literal instead of ending the literal.
• An underscore after an underscore includes a single underscore in the literal.
• White space (any number of blanks, tabs or newlines) following an underscore is ignored, and not included in the literal.

Examples:

```"This literal is a _"string-style_" literal."
"This literal contains a single underscore: '__'."

s := "This literal is moderately long, and is broken _
over two lines, even though the result is a single line."
```
When using `#include "aldor"` or `#include "axiom"`, the type `String` provides string-style literals.

Integer literals

Integer-style literals provide a syntax for whole numbers. These are in base ten unless otherwise indicated.

An integer-style literal is either

• a sequence of one or more digits, [0-9]+, with the exception of a single "`0`" or single "`1`", or
• a sequence of one or more digits giving a radix (base), followed by the letter "`r`", followed by a number of radix-digits using digits and/or capital letters: [0-9]+r[0-9A-Z]+.

In Aldor the numerals "`0`" and "`1`" are not literal constants - they are treated as names so that various mathematical structures which export 0 or 1 can do so, without being required to support general integer constants.

An underscore appearing in the middle of an integer-style literal is ignored together with any following white space. An underscore which appears at the very beginning of a word causes the whole word to be treated as an identifier, rather than as a literal constant.

Examples:

```22_394_547

38319238471239487123948237_
192387491234712398478188_
139823712983712938712391

_33    -- This word is an identifier, not an integer-style literal.

2r01010101010101010101    -- Base 2
16rDEADBEEF               -- Base 16
```

When using `#include "aldor"`, the types `SingleInteger` and `Integer` provide integer-style literals. When using `#include "axiom"`, the types `SingleInteger`, `Integer`, `NonNegativeInteger` and `PositiveInteger`provide integer-style literals.

None of the above types support the baservalue radix notation described above.

Floating-point literals

Float-style literals are numbers with a decimal point, an exponent, or both.

Examples:

```3.0        3.       3e1     6.022E+23
0.2        .2       2e-1    4.8481E-6
```

An underscore appearing in the middle of a float-style literal is ignored together with any following white space.

```3.14159_26535_89793_23846_26433_83279_50288_41971_
69399_37510_58209_74944_59230_78164_06286_20899_
86280_34825_34211_70679_82148_08651_32823_06647
```

When using `#include "aldor"`, the types `SingleFloat`, `DoubleFloat` and `Float` provide float-style literals. When using `#include "axiom"`, the types `DoubleFloat` and `Float` provide float-style literals.

None of the above types support the baservaluer radix notation.

### 5.3 : Definitions

A constant in Aldor denotes a particular value which cannot be changed. The general syntax for a constant definition is:

```x : T == E
```

`x` is an identifier giving the name of the constant.

`T` is an expression giving the type of the constant. The type declaration is optional. If the type is declared, then the type of `E` must satisfy it. Otherwise the type is inferred from the type of the expression `E`.

`E` is an expression which computes the value of the constant.

Examples:

```a : Integer == 23;
b == "Hello world!";
```

A function definition is a special case of a constant definition. Function definitions are described in more detail in section 6.1.

Once a value has been given to a named constant, it cannot be changed to refer to another value.

```-- A constant cannot be changed to refer to a different value.
num: Integer == 3;
num: Integer == 4;

-- In fact, it cannot be changed to refer to the same value!
hi:  String  == "'Ello!";
hi:  String  == "'Ello!";
```

### 5.4 : Assignments

A variable in Aldor denotes a value which may change during the evaluation of a program. A variable is given a value by an assignment of the form:

```x : T := E
```

`x` is an identifier giving the name of the variable.

`T` is an expression giving the type of the variable. The type declaration is optional. If the type is declared, then the type of `E` must satisfy it. Otherwise the type is inferred from the type of the expression `E`.

`E` is an expression which computes the value of the variable.

Several variables may be assigned a value at the same time:

```(x1 : T1, ..., xn: Tn) := E
```

Any or all of the type declarations may be omitted, in which case the ith variable would read "`xi`", rather than "`xi: Ti`", and the type of `xi` is inferred from the type of the expression `E`.

Examples:

```n: Integer := 3;
k := 3*n + 1;
n := k quo 2;

(a, b) := (1, 3);
(s: String, x) := ("Natascia", false);
```

The value of an assignment expression is the same as the value of `E`.

A special form of assignment expression is used to provide a general kind of updating operation:

```x(a1, ..., an) := E
```

Typically, `x` is an expression which evaluates to a structured data value, such as an array or a list, and the expressions `ai` taken together specify some component of `x`. An assignment expression of this form is treated as an application of the operation "`set!`" of the form:

```set!(x, a1, ..., an, E)
```

For example, for lists, the "`set!`" function (see section 25.19) takes as its second (component specifying) parameter either "`first`" or "`rest`", so we could have:

```#include "aldor";
import from SingleInteger, List SingleInteger;
L := [1,2,3];
...
L(first) := 4;
```

which would result in `L` having the value `list(4, 2, 3)`.

The value of this form is the return value of the function "`set!`".

### 5.5 : Functions

Function expressions are the primitive form for building functions in Aldor. An example of a function expression is:

```(n: Integer, m: Integer): Integer +-> n * m + 1
```

See section 6.5 for a complete description.

### 5.6 : Functions calls

Typical expressions consist mostly of function calls. For example, consider the expression

```l: List Integer := list(2 + 3, 4 - 5, 6 * 7, 8 ^ 9)
```

### 5.7 : Imperatives

The `do` expression evaluates `E` and discards the computed value, so that the `do` expression returns no value.

```do E
```

### 5.8 : Multiple values

A series of comma-separated expressions is used in Aldor to produce multiple values. The expressions are evaluated one by one, and the results are taken together as the (multiple) value of the whole expression:

```3, 4, 5
```

This expression produces three values, all of type Integer. In general, an expression in Aldor produces zero, one or more values, each having its own type. For convenience, nevertheless, we often speak of the value and the type of an expression, even if it produces multiple values, when the intended meaning is clear from the context.

See
section 4.7 for a discussion of the use of parentheses in comma expressions.

Functions may be declared to accept or return multiple values. The example below shows how to declare, define and use a function which involves multiple values.

```#include "aldor"

-- Declaring a function to accept and return multiple values.
local f: (Integer, Integer) -> (Integer, Integer);

-- Defining a function to accept and return multiple values.
f(i: Integer, j: Integer): (Integer, Integer) == (i+j, i-j);

-- Using a function which accepts and returns multiple values.
(q: Integer, r: Integer) := divide f(100, 93);
print << "The quotient is  " << q << newline;
print << "The remainder is " << r << newline;
```

The call to `f` returns `(193, 7)`, which are passed as arguments to the function "`divide`" from `Integer`. This returns

```(193 quo 7, 193 rem 7)
```

which are assigned to `q` and `r` respectively.

Comma-separated expressions are not necessarily evaluated in any particular order; furthermore, the evaluation of their subexpression may be interleaved. Thus, the program:

```#include "aldor"

pr2(a: SingleInteger, b: SingleInteger): () ==
print << a << " " << b << newline;

n: SingleInteger := 1;

pr2({n := n + 1; n}, {n := n + 1; n})
```

could print any of "`2 3`", "`3 2`", "`2 2`" or "`3 3`". Programs which depend on the order of evaluation of expressions to be used as arguments to a function should use a sequence to make the order explicit. (See section 5.9.)

### 5.9 : Sequences

A series of expressions to be evaluated one after another is called a sequence. A sequence is written as a semicolon-separated series of subexpressions:

```a := 1; b := a + a; c := 3*b
```

The expressions (that is, the subexpressions of the sequence) are evaluated one by one, in the order of their occurrence, and the value of the last expression evaluated is used as the value of the sequence. A sequence may also contain one or more exit expressions, as described in section5.10, which prevent the evaluation of any expressions later in the sequence and so provide a way to return a value other than that of the last expression in the sequence.

Because semicolon has a relatively low precedence, it is usually necessary to enclose a sequence in braces ("`{ }`") or parentheses ("`( )`") to get the desired result. (See section 4.7 for details.)

Examples:

```#include "aldor"

import from SingleInteger;

n1 := (a := 1; b := a + a;  3 * b);
n2 := {a := 1; b := a + a;  3 * b}

f(i0: SingleInteger): SingleInteger == {
a := i0;
b := a + a;
3 * b
}
```

The meaning of a sequence is the same whether braces or parentheses are used. Braces are normally used, especially to enclose a longer expression split over several lines. Parentheses are occasionally used to enclose shorter sequences as part of other expressions. An implicit semicolon is assumed after a closing brace but not after a closing parenthesis.

It is also possible to use indentation to construct sequences by enclosing lines between the directives "`#pile`" and "`#endpile`". In this context, a group of consecutive lines indented by the same amount is called a pile and is treated as a sequence. The precise rules for forming piles are described in section 24.3.

### 5.10 : Exits

An exit expression has the form:

```condition => E
```

When an exit expression appears as one of the elements of a sequence, the condition is evaluated. If the condition evaluates to `true` then the value of the sequence is the value of the expression `E`, and no further components of the sequences are evaluated. If the condition evaluates to `false` then evaluation continues with the next expression in the sequence. So the expression:

```{ a; b; c => d; e; f }
```

is equivalent to

```{ a; b; if c then d else { e; f } }
```

In a sequence which contains an exit expression, the type of the expression `E` must be compatible with the type of the sequence, that is, with the type of the final element of the sequence. If a sequence contains several exit expressions, the types of the possible exit values must all be compatible.

If the condition is not of type `Boolean`, then an implicit application of the function test is performed to convert the condition to the type `Boolean`. (See
section 11.2.)

An exit expression transfers control; it does not, itself, produce a value. As a result, the type of the exit expression is `()`, and so an exit expression can only be used in a context which does not require a value. Examples:

```#include "aldor"

import from Integer;

b: Integer := 1;

a := { n := b * b; n < 10 => 0; n > 100 => 100 ; n }

-- `a' will be assigned the value `0', corresponding to the
-- right hand side of the first `=>'
```

Note that all of the exit values (i.e. 0 and 100) have type `Integer`, and the final element of the sequence also has type `Integer`.

A series of exit expressions is often a compact way to enumerate a list of alternative cases:

```#include "aldor"

import from Integer;

power(base: Integer, exp: Integer): Integer == {
exp = 0 => 1;
exp = 1 => base;
exp = 2 => base * base;
exp = 3 => base * base * base;

val := 1;

for i in 1..exp repeat val := val * base;

val;
}
print << power(2, 0) << newline;  -- Print `1'
print << power(2, 1) << newline;  -- Print `2'
print << power(2, 2) << newline;  -- Print `4'
print << power(2, 3) << newline;  -- Print `8'
print << power(2, 9) << newline;  -- Print `512'
```

Since any expression can appear after the =>, another sequence, which may contain other exit expressions, can appear there:

```#include "aldor"

import from Integer;

+++ If `a' or `b' is zero, then return 0;
+++ Otherwise return 1 if (a * b > 0), -1 elsewhere.
productSign(a: Integer, b: Integer): Integer == {
a = 0 => 0;
b = 0 => 0;
a < 0 => { b < 0 => 1; -1 }
b > 0 => 1;
-1
}
```

If an exit expression appears as a strict subexpression of an expression other than a sequence, the exit expression is treated as a sequence of length one:

```if b < 0 then a > 0 => flag := false;
```

This example is treated as equivalent to:

```if b < 0 then { a > 0 => flag := false }
```

### 5.11 : If

Conditional branching in Aldor is provided by the if expression.

```if condition then T
if condition then T else E
```
```#include "aldor"
import from SingleInteger;

foo(a: SingleInteger): SingleInteger ==
if a > 0 then a * a else 0
```

Note that if the `else` clause is not present, then the `if` expression cannot be used in a context which requires a value:

```-- This assignment is not type correct.
a : SingleInteger := if true then 1;
```

### 5.12 : Logical expressions

Logical expressions in Aldor are provided using the following forms:

```E1 and E2
E1 or  E2
not E
```
```#include "aldor"

if true and false then print << "This string will not be printed.";

import from SingleInteger, String;

-- Define `test' for SingleInteger:  a null value returns false.
test(x: SingleInteger): Boolean == if x = 0 then false else true;

if 1 or 1 then print << "I can do this." << newline;

-- Define `test' for String:  an empty string returns false.
-- Note that `#s' (`the length of s') uses
-- the previous test for SingleInteger.
test(s: String): Boolean == if #s then true else false;

if true and 1 and "I can do this, too." then
print << "This string will be printed."
```

The logical connectives "`and`", "`or`" and "`not`" are syntactic elements of the language that should not be confused with similar functions exported from the type `Boolean` (`/\`, `\/` and `~`). The functional versions from `Boolean` evaluate all of their arguments before computing their result, and denote function values. The logical connectives cannot be used as functions:

```#include "aldor"

import from List Boolean;

-- This expression will print:  `list(true, true, false)'
print << map(~, [false, false, true]);
```

but you cannot say: `map(not, [false, false, true])`, since "`not`" is not a function. (The Aldor function "`map`", defined for all aggregate types (see section 25.3 applies its first argument to each component of its second argument.)

### 5.13 : Loops

The Aldor language provdes a set of constructs to handle loops in a way which is both elegant and efficient. The concept lying at the base of Aldor loops is that of generator, discussed in depth in chapter9. Generators provide an abstract way to traverse values belonging to certain domains without violating the principle of encapsulation (see section 7.8). Generators can be considered as autonomous entities producing values. This section shows how values they produce can be used to control loops.

The general form of a loop expression is:

Iterators repeat Body

The iterators control how many times the body is evaluated. Any number of iterators may be used on a loop, and each is either a "while" or a "for" iterator.

A loop with no iterator repeats forever, unless terminated by an error or some other event. For example:

```#include "aldor"

-- This will repeat forever...

repeat {
print << "Row, row, row your boat," << newline;
print << "Gently down the stream." << newline;
print << "Merrily, merrily, merrily , merrily," << newline;
print << "Life is but a dream." << newline;
print << newline;
}
```

Two forms, "break" and "iterate," may be used withing the loop body to control the loop evaluation, as described later on.

While-iterators

A "while" iterator, allows a loop to continue so long as a condition remains true. The syntax of a "while" iterator is

```while condition
```
If a loop has a "while" iterator, then at the beginning of each iteration condition is evaluated. The result is then tested:
• If it is true, the evaluation of the loop proceeds.
• If it is false, then the loop is terminated.

Just as with "if" and other expressions having tests for control flow, if the condition of a"while" is not a Boolean value, then an appropriate "test" function is applied to determine the sense of the condition.

The following example shows a repeat loop using a while iterator:

```#include "aldor"

import from Integer;

n := 10000;
k := 0;        -- 'k' counts the number of iterations.

while n ~= 1 repeat {
k := k + 1;

if odd? n then n := 3*n + 1 else n:= n quo 2;
}
print << "terminated after " << k << " iterations." << newline;
```

This loop counts the number of times the body has to be evaluated in order for n to reach one. When n reaches 1, the evaluation of the loop is terminated, and the count is printed. (It is a well-known conjecture that this process will terminate for all integer n > 0. This is sometimes called the "3n + 1 problem".)

In a case such as this it is important to give k an initial value, since the loop may be iterated zero times! In fact, if the while condition is false the first time that it is evaluated, then the repeat body will not be executed at all:

```#include "aldor"

import from Integer;

n := 0;

while n > 0 repeat {
-- This will never be executed.
print << "Hello world!" << newline;
}
```

For-iterators

Very often, loops are used to traverse certain kinds of data structures, such as lists, arrays or tables, or to execute some operations for all the numerical values in a defined range.

"for" iterators make this sort of loop convenient to write. Take, for instance, the following examples:

```-- Add up the elements of a list, return the sum.
sum(ls: List Integer): Integer == {
n := 0;
for i in ls repeat n := n + i;
n
}

-- Add up the elements of an array, return the sum.
sum(arr: Array Integer): Integer == {
n := 0;
for i in arr repeat n := n + i;
n
}

-- Add up the odd numbers in a range, return the sum.
sum(lo: Integer, hi: Integer): Integer == {
n := 0;
if even? lo then lo := lo + 1;

for i in lo..hi by 2 repeat n := n + i;
n
}

import from List Integer;

-- Use 'sum: List Integer -> Integer':
print << sum([1,2,3,4])     -- Prints '10'.
```

The "for" iterators in these examples all have the form

`for lhs in Expr`

The lhs part specifies a varable which will take on the successive values over the course of the iteration. The lhs has the form

`[free] name [: Type]`

The type declaration is optional. If it is missing, the type of the variable is inferred from the source of the values, Expr

The "free" part of the lhs determines the scope of the variable. Without it, a new variable of the given name is made local to the loop. If the word "free" is present, then the loop uses an existing variable from the context. In this case, the value of the variable is available after the loop terminates.

The example above can be rewritten useing a free loop variable:

```# include "aldor"

import from Integer;

n := 10000;
k := 0                        -- Make a top-level variable 'k'.

for free k in 1.. repeat {   -- Use above 'k' freely in the loop.

if odd? n then n := 3*n + 1 else n := n quo 2;

if n = 1 then break; -- exit the loop if n = 1
}

-- Here the last value of 'k' is available.
print << "terminated after " << k << " iterations." << newline;
```

The previous example uses the "break" construct explained later in this section. When a break is evaluated it causes the termination of the loop. In this case, the break is the only exit point of the loop, because we are iterating over an open segment, producing infinitely many values: 1, 2, 3, ...

Now we turn our attention to the expression traversed by the "for" iterator. In the examples, we have seen

• a list, "i",
• an array, "a", and
• integer segments, "lo..hi by 2" and "1..".

In general, the "for" iterator expression must have type Generator T, where T is the type of the "for" variable. If the expression is not of this type, then an implicit type will be used. See chapter 9 for a description of generators and how to create new ones.

The examples we have seen work because the list, array and segment types provided by "libaldor" export generator functions. Other examples of generators provided by "libaldor" are "step", provided by SingleFloat, DoubleFloat and Float, which creates uniformly spaced points on a floting point interval, and "tails" which provides successive tails of a list.

There is a second form of "for" iterator which filters the values used. This has the form:

```for lhs in Expr | condition
```

This kind of "for" iterator skips those values which do not satisfy the condition. For example, the sum example we saw earlier could have been wrtten as:

```#include "aldor"

-- Add up the odd numbers in a range
sum(lo: Integer, hi: Integer): Integer == }
n := 0;
for i in lo..hi | odd? i repeat n := n + 1;
n
}
```

Multiple interators

A "repeat" loop may have any number of iterators, with the following syntax:

```iterator1 ... iteratorn repeat Body
```

The loop is repreated until one of the iterators terminates it: the first "while" which has false condition or the first "for" which consumes all its values ends the loop.

This is convenient when the termination condition does not relate directly to a "for" variable, or when structures are to be traversed in parallel.

Continuing the example from earlier, we may use a "while" to decide if the end has been reached, and, at the same time, use a "for" to count the number of times we have evaluated the loop body:

```#include "aldor"

import from Integer;

n := 10000;
k := 0;

while n ~= 1 for free k in 1.. repeat
if odd? n then n := 3*n + 1 else n := n quo 2;

print << "Terminated after " << k << " iterations." << newline;
```

Multiple "for" iterators can allow lists to be combined in an efficient way:

```#include "aldor"
import from List Integer;

l1 := [1,2,3];
l2 := [8,7,6,5];

-- Add the pair-wise products in two lists.
x := 0;
for n1 in l1 for n2 in l2 repeat
x := x + n1 * n2

print << "The result is " << x << newline
```

These two "for" iterators are used in parallel, like a zipper combining the two lists. The loop stops at the end of the shortest list, in this case giving a sum of three products.

This is not a double loop - to use all pairs with the number from l1 and the second number from ls, you would use two nested loops, each with its own "repeat":

```#include "aldor"
import from List Integer;

l1 : [1,2,3];
l2 : [8,7,6,5];

x := 0;
for n1 in l1 repreat
for n2 in l2 repeat
x := x + n1 * n2;

print << "The result is " << x << newline
```

Using more than one iterator is often the most efficient natural way to write a loop. A loop with two "for" iterators is more efficient than

```...
m: SingleInteger := min(#l1, #l2);
for i in 1..m repeat
x := x + l1.i * l2.i
```

because it does not need to traverse the lists each time to pick off the desired elements. And the code is more concise than

```...
t1 := l1;
t2 := l2;
while (not empty? t1 and not empty? t2) repeat {
x := x + first t1 * first t2;
t1 := rest t1;
t2 := rest t2;
}
```

Evaluating a "break" causes a loop to terminate. For example:

```#include "aldor"

import from Integer;

n := 10000;
k := 0;        -- 'k' counts the number of iterations.

repeat {
if odd? n then n := 3*n + 1 else n := n quo 2;

k := k + 1;

if n = 1 then break;
}
print << "Terminated after " << k << " iterations." << newline
```

"break" is most useful when the condition which quits the loop falls most naturally in the middle or at the end of the loop body. Sometimes it is possible to change a test which appears at the end to a test at the begining. This helps make programs more readable, since one sees immediately what will cause the loop to end. Also, it allows the exit to be controlled by a "while" iterator, rather than an "if" and a "break".

Iterate

Evaluating an "iterate" abandons the current evaluation of the loop body and starts the next iteration. For example:

```#include "aldor"

import from Integer;

n := 10000;
k := 0;         -- 'k' counts the number of iterations.

repeat {
k := k + 1;
if odd? n then { n := 3*n + 1; iterate }

n := n quo 2;
if n = 1 then break
}
print << "Terminated after " << k << " iterations." << newline;
```

This example does the same thing as the previous one, but is organized slightly differently. The "iterate" on the second line of the loop body causes the rest of the body to be skipped.

"iterate" can be used instread of placing the remainder of a loop body inside an "if" expression. This can make programs easier to read, by emphasizing that certain conditions are not expected, and by avoiding extra levels of indentation. It is particularly useful when the decision to go on to the next iteration of a loop is buried deep inside some other logic, rather than appearing at the top level of the loop body.

An "iterate" is equivalent to a "goto" branching to the end of the loop body. Thus, the meaning of "iterate" is independent of whether there are any "while" or "for" iterators controlling the loop.

If an "iterate" occurs inside nested loops, it steps the deepest one.

Definition in low-level terms

It is possible to express the loop behavious in terms of gotos and labels. A loop of the form

`it1 it2 ... itn repeat Body`

is equivalent to

```{
init1; init2; ... initn;
@TOP
step1; step2; ... stepn;
Body;
goto TOP;
@DONE
}
```

Where, if iti is "while condi", then initi is empty and stepi is

```if not condi then goto DONE
```

if iti is "for lhsi in expri | condi", then initi is

`gi := generator expri;`

and stepi is

```step! gi;
if empty? gi then goto DONE
lhsi := value gi
if not condi then goto TOP
```

(a "for" without a condition is treated as if the condition were "true").

In this, TOP, DONE and the gi are generated names, and are not accessible to the other parts of the program.

### 5.14 : Generate expressions

Generate expressions are used to create generators. For a complete description of how to use generate to create a generator, see chapter 9. The general syntax for a generate expression is:

```generate E
generate to n of E
```

E is an expression which represents code which will be evaluated each time a value is extracted from the generator. Evaluation begins at the start of the expression E and continues until an expression of the form

```yield v
```

is processed, where v is the value to be passed back to the context which is collecting values from the generator. Each time a value is requested after the first value is yielded, control resumes after the yield expression which produced the previous value.

### 5.15 : Collections

```#include "aldor"
...
import from Integer, List Integer;
print << [x*x for x in 1..10] << newline;
print << [x*y for x in 1..10 for y in 10..1 by -1];
```

This program creates a list of the squares of the integers from 1 to 10, and then a list of products of integers. Note that while can form an iterator, and can therefore be used in a collect expression.

Note that the square brackets are not part of the collect expression, but are simply a shorthand for a call to the function bracket, with the value of the collection as an argument. The domain List Integer from the Aldor base library exports a function with the signature `bracket: Generator Integer -> %`, which is called twice in the above example.

As collect expressions produce generators, one would expect that generate expressions and collect expressions are related. The collect expression:

E iter1 ... itern

is equivalent to the generate expression:

generate iter1 ... itern repeat yield E

Thus, x*y for x in 1..9 for y in 9..1 by -1 is the same as:

generate for x in 1..9 for y in 9..1 by -1 repeat yield x*y

Collect expressions provide a convenient notation for creating new aggregates, and require no additional functionality in the language.

### 5.16 : General branching

Aldor provides unconditional branching using label expressions and goto expressions. A label expression is of the following form:

```@L E
```

where `L` is an identifier known as the label name, and `E` is any expression. The type of the label expression is the same as the type of `E`. Names which are used as labels have no relationship with variables or constants of the same name, and a label name may also be used as a variable or constant. A label name obeys the same scope rules as constants or variables, but may not appear in any expressions other than gotos and other label expressions. Since labels are constants, it is an error to bind the same label twice in the same scope.

A goto expression has the following form:

```goto L
```

where `L` is the name of a label. After the evaluation of a goto expression, execution resumes with the expression associated with the label `L`. The type of the goto expression itself is the type `Exit`.

The label must appear in the same function body as the `goto`. In addition, it is an error for a `goto` to branch into an inner scope of the scope in which it appears (that is, a local function or any repeat or collection including a for, where, add or with expression). A `goto` may also not branch out of a function or a with or add expression.

Example:

```foo(a: SingleInteger): SingleInteger == {
if a <= 0 then goto ERROR;

return a * a;

@ERROR
print << "The argument must be a positive value!" << newline;
0
}
```

If the first test is successful, then the return expression is skipped and the execution proceeds on the line following ERROR. Labels can also be defined at the top level of a file, since the top level of a file is treated as a sequence:

```#include "aldor"

@LAB1
print << "You will see this forever..." << newline;
goto LAB1;
```

### 5.17 : Never

The expression never is a special value, of type `Exit`, which acts as a programmer-supplied assertion that execution will never reach that point. An exit expression can be useful as it may allow a program to be translated into more efficient code.

The following Aldor code is a possible use of never

```s := {
x = 0 => "zero";
x > 0 => "positive";
x < 0 => "negative";
-- This expression is unreachable
never
}
```

With luck, the never at the end of the sequence will not be reached in any execution of the program. (If it is reached, Aldor will complain "User error: Reached a "never""). Previous Home Contents Next