Tuples, tuples and more tuples

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");