Tuples

Tuples are used for keeping several (related) kinds of data together in one variable, e.g. the identification number and weight of a box. A tuple consists of a number of fields, where the types of these fields may be different. The number of fields is fixed. For instance, consider the following:

disc tuple(int nr; real weight) box;

Variable box has a tuple type, consisting of two fields, an integer typed field with name nr and real typed field with name weight. The box variable has essentially two values, an integer typed value, and a real typed value.

If multiple consecutive fields have the same type, the type need not be repeated for each of them. In the following example, variables x1 and x2 have the same type:

disc tuple(int a; int b; real c; int d) x1;
disc tuple(int a, b;     real c; int d) x2;

Literal values exist for tuple types:

disc tuple(int nr; real weight) box = (5, 2.7);

edge ... do box := (6, 3.4);

The box variable is initialized to a tuple value consisting of integer value 5 (identification number) and real value 2.7 (weight). The entire value of the variable is reassigned in the assignment. That is, both fields are given new values.

It is also possible to refer to a specific field of a tuple, using projection:

disc tuple(int nr; real weight) box = (5, 2.7);
disc int i;
disc real r;

edge ... do i := box[nr];            // Projection to field 'nr'.
edge ... do r := box[weight];        // Projection to field 'weight'.
edge ... do box[nr] := i;            // Assignment to field 'nr'.
edge ... do box[nr] := box[nr] + 1;  // Increment of field 'nr'.

The first edge uses projection to obtain the value of the integer nr field, and assign it to integer variable i (i becomes 5). The second edge performs a similar operation for the weight field (r becomes 2.7). The third edge assigns the value of integer variable i to the integer field nr of the box variable. This changes only the value of the nr field. The value of the weight field of the box variable is not affected by this assignment. The third edge increments the value of the nr field of the box variable by one, leaving the weight of the box as is. Besides projection using field names, it is also possible to do projection using 0-based indices:

disc tuple(int nr; real weight) box = (5, 2.7);
disc int i;
disc real r;

edge ... do i := box[0];  // Projection to field 'nr'.
edge ... do r := box[1];  // Projection to field 'weight'.

Index 0 refers to the first field, in this case field nr. Index 1 refers to the second field, etc. Projection using indices is also called indexing. For tuples, it is usually preferred to use field names, rather than indices, for readability.

It is possible to create a tuple from separate values, each stored in a variable:

disc tuple(int nr; real weight) box;
disc int i;
disc real r;

edge ... do box := (i, r); // Packing a tuple.

The right hand side of the assignment is a tuple literal value, as used before. The field values however, are obtained by evaluation of variables, rather than using literal integer and real values. This kind of assignment, where there is tuple variable at the left hand side, and values for each of the fields of that tuple at the right hand side, is called packing a tuple.

It is possible to obtain the values of the fields of a tuple into separate variables:

disc tuple(int nr; real weight) box = (5, 2.7);
disc int i;
disc real r;

edge ... do i := box[nr], r := box[weight];
edge ... do (i, r) := box; // Unpacking a tuple.

The first edge uses projection on the variable box to obtain the values of the individual fields, and assigns those extracted values to two separate variables. The second edge does the same thing as the first edge, and is preferred in this case, because of its simple and short notation. This kind of use, where at the left hand side of the assignment you see variables for each of the fields of the tuple, and on the right hand side you see only one variable that has a tuple type, is called unpacking a tuple.