Tuples are used a lot in F#. Let’s start with a definition
A tuple is a grouping of unnamed but ordered values, possibly of different type
This was take from Tuples (F#) and I’d highly recommend reading this. I will undoubtedly recreate some of the information from this document here, but hopefully add something of use.
Declaring tuples
So we’ve got a definition (above) for what a tuple is, now let’s have a look at some
let tupleInts = (1, 2, 3, 4)
let tupleStrings = ("one", "two", "three")
let tupleValues = (a, b, c, d)
let tupleMixed = ("one", 2, c)
let tupleExpressions = (a + 1, b + 2, c + 3)
The above should be pretty self explanatory.
If we take the first tuple, name tupleInts, and run this in the F# interactive window we’ll see that this translates to val tupleInts : int * int * int * int = (1, 2, 3, 4). The * denoting a tuple. In this case you can see that each item/element in the tuple is of type int.
Getting values from a tuple
Using let bindings
let (a, b) = (1, 2)
Using let bindings but ignore one or more elements (i.e. using the _ wildcard character)
let (a, b, _) = (1, 2, 3)
// or
let a, b, _ = (1, 2, 3)
Using pattern matching
let tuple = (1, 2, 3)
let pattern t =
match t with
| (a, b, c) -> printfn "%d" a
pattern tuple
We can use the fst and snd functions which get the first or second elements from the tuple, i.e.
let a = fst (1, 2)
let b = snd (1, 2)
Obviously a will have the value 1 and bReturning multiple values
We can obviously pass multiple values into a function using a tuple, but we can also return a tuple and hence return multiple values as per
let inc a b = (a + 1, b + 1)
where the return is a tuple of the values (a + 1, b + 1)
Cross language
In C# (.NET 4.0) we have the Tuple generic class which we can create in one of two ways
Tuple<int, int> tuple = mew Tuple<int, int>(1, 2);
// or using the helper method
var tuple = Tuple.Create(1, 2);
F# uses the same Tuple class internally (we can confirm this by checking the IL using ILSpy or the likes) to represent it’s tuples. However, as seen, it’s more of a language feature in F#. Hence we have the syntactic sugar to allow us to create the tuple just using (item1, item2).
Obviously if we can create a Tuple in C# and the underlying representation of a tuple in F# is the same, we can pass data to and from each language using this mechanism. So for example if we had this rather contrived C# code
public static class Data
{
public static Tuple<int, string> Get()
{
return Tuple.Create(123, "One Two Three");
}
public static void Set(Tuple<int, string> tuple)
{
Console.WriteLine(tuple.Item1 + " - " + tuple.Item2);
}
}
and in F# we can interact with these methods as follows
let (num, value) = CSharpLib.Data.Get()
CSharpLib.Data.Set(321, "Three Two One");