Maybe the best thing to do is to start by showing a few examples of tuples:
let amigo = ("Sebastián", 7)
let pair1 = (3, 2)
let pair2 = (2, 5)
let student = "Santiago", "Monterrey", 2007, true
The first tuple ("Sebastián", 7) groups two values: a string and an integer, allowing us to handle them as just one thing, this "thing" has the type string * int, that is, it belongs to the set of all the combinations of strings and integers, in this sense ("Sebastián", 7) has the same type of ("Alejandra", 19). By the way, note how we separate the different elements of the tuple with commas.
Tuples pair1 and pair2 are of type (make a wild guess...) int * int. Strictly speaking, "let pair1 = (3, 2)" defines a function pair1 that always returns the same tuple (3, 2), that is, it's a constant function that takes 0 parameters.
Finally, the student tuple is of type string * string * int * bool, the fact that I have omitted the parenthesis is not a mistake, tuples actually don't need them and many F# programmers don't put them (even though, I personally prefer to write them down, to remind myself that what I am seeing is something to be treated as a whole).
With these tuples in our hands, we can define some functions:
let addPairs (x1,y1) (x2, y2) = x1 + x2, y1 + y2
let primero (p, q) = p
let getYear (name, city, year, status) = year
let getYearFunny (_, _, year, _) = year
addPairs is a function that receives two tuples and returns another (to be precise, its type is int * int -> int * int -> int * int). Just to get used to it, I omitted the parenthesis in the function body (but I insist: I don't think it's a good idea).
The function primero is even more interesting: its type is... 'a * 'b -> 'a, which means that it receives a tuple containing some stuff and some other stuff and returns something of the same type of the first stuff. Maybe we expected the type to be something like int * int -> int, but that would have unnecessarily limited the usability of the function. For example, we can now say "primero amigo" and get the string "Santiago" or "primero pair1" and get the integer 3. If you think about it, the use of 'a and 'b is very similar to the use of generics in C# or VB.NET. It's utterly important to note that primero does *not* receive two parameters p and q but just one parameter, namely a two-value tuple, and then the function body tells that what must be returned is the first of those two values, this is a simple example of F# pattern matching. By the way, it's really not necessary to write the primero function, because F# already provides us with fst and snd.
A somewhat more complex example of pattern matching is getYear, which gets a tuple of type 'a * 'b * 'c * 'd and returns a 'c. "getYear student" of course returns 2007 (what is returned by getYear ("William", "Jones", 1706, 3.1416)? Is this even possible?). It's interesting to note that even though in getYear definition we name the four elements of the tuple, we use just one of them, which takes us to the definition of getYearFunny: the "_" symbol (underscore) basically means "an element whose value I don't care about", and so getYearFunny ignores the first, second, and fourth values in the tuple. This is our first encounter with this "_" guy and we'll find out that it appears frequently and that it's very useful when doing pattern matching.
Finally, let's mention a few more characteristics and uses of tuples:
- A tuple have a fixed number of elements: be them two, three or thirty, once set you can't add or remove elements from a tuple
- The elements in a tuple doesn't have a name, you access them by their position in the tuple with the help of pattern matching
- It's almost redundant to say, but a tuple may contain other tuples, e.g. what's the value of fst (snd ("Santiago" (9, 10))) ? Do we need all the parenthesis?
- A tuple is a handy way of making a function return multiple values (as the original getYear does) or to pass multiple values to a function that expects only one parameter
Tuples are a basic and simple component of F#, built to represent a fixed-size sequential set of values.