1,2 "Hello", "World" (1, 2.7, "Hello") ()The comma chain operator constructs tuples. While brackets are not always necessary, the comma operator has a low precedence so tuples usually appear in brackets. Notice there is a special unique empty tuple '()'. There are no tuples with one component: for all values 'a', '(a)' is equivalent.
Now perhaps you have guessed what I meant earlier when I said the function mid only had a single argument. If not, you get another chance, studying this example, which is equivalent to example 106.
1: include "std"; 2: fun mid(a:int, b:int):int = 3: { 4: val c = (a + b) / 2; 5: return c; 6: } 7: val x = (2,4); 8: print (mid x); print "\n";
A tuple is a product type: you may be familiar with the Cartesian product of sets. The notation for tuple types is the same, except of course we use '*' instead of a multiply sign: here is the declaration of x with a type annotation:
val x : int * int = (2,4);You should note that tuple construction is not associative. Here are three tuple value declarations with type annotations:
val x : int * int * int = (1,2,3); val y : (int * int) * int = ((1,2),3); val z : int * (int * int) = (1,(2,3));These three tuples have distinct types and values. The first has three components, each of type int. The other two have two components each: an int and a pair of ints, in the two possible orderings.
The type of the empty tuple '()' is called 'unit'. It can also be called '1', the reason will become clear soon.
I said before that 'almost' all functions in Felix have one argument. The tuple constructor is the exception.
You can get at tuple components using a suffixed dot followed a zero origin integer in brackets:
1: include "std"; 2: val x = (0,1,(3,4)); 3: print x.(0); print " "; 4: print x.(1); print " "; 5: print x.(2).(0); print " "; 6: print x.(2).(1); print "\n";