Group Data Objects into Tuples
Learn how to group data objects into pairs and tuples, as well as decompose them using pattern matching.
We'll cover the following...
Primitive datatypes such as integers, floats, booleans, and strings are useful but often not sufficient. Yet, when modeling real-world phenomena, we often need to glue together data to form compound data. Consider the example of developing a software package for 2D graphics. To represent, say, a point we could use two separate float
numbers denoting its x and y coordinate. But this could get messy because we would need to keep track of what x
and y
coordinates belong to what point. It’s much better to glue an x
and y
coordinate into a compound data object like a pair and treat the point as a single concept.
Construct tuples
OCaml and many other functional programming languages provide the tuples type to group multiple data objects into a single compound data object called a tuple. We construct a tuple by placing values into parentheses delimited by commas. For example, we can create a pair, which are tuples of 2 elements.
(42, "Hi FP")
The order of the elements in a pair is crucial. For instance, ("Hi FP", 42)
is an entirely different pair.
Moreover, as seen in this example, a pair may contain elements of different types. In our example, utop
shows the type of (42, "Hi FP")
as int * string
.
In general, the pair type, whose first element’s type is t1
and the second one is t2
, is t1 * t2
(read t1
cross t2
).
Tuples have a fixed number of elements and hence are most suited for use cases in which we know the number of elements to be stored in advance. In particular, pa pair is ideal for representing a 2D point because we need x
and y
coordinates. We can, for example, define a point with x
coordinate = 2.0
and y
coordinate = 1.0
as follows:
let p = (2., 1.)
Other concepts representable as pairs are
rational numbers, p/q
, and complex numbers, a + bi
, where a
is the real part and b
the imaginary part.
Of course, we can store tuples within tuples. For example, we can construct the following pair whose second element is another pair.
(1, (2, "FP"))
The functional programming language Scheme uses this ability to represent a list as a chain of nested pairs.
For instance, the sequence, 1, 2, 3, 4
, can be represented as (1, (2, (3, (4, nil))))
in Scheme where nil
represents an empty list.
In OCaml and Haskell, lists are defined using algebraic datatypes.
Tuples are particularly handy when we want to return more than one value from a function. For instance, when computing an integer division, it can be helpful to obtain the quotient and the remainder at the same time.
We can write a div_mod
function that does integer division of two integers and returns the ...
(** [print_int_pair (x, y)] prints a pair of integers to the console. *)let print_int_pair (x, y) = Printf.printf "(%d, %d)" x y(** [div_mode x, y] returns a pair containing the quotient and remainder of x divides by y. *)let div_mod x y = (x / y, x mod y)(** Printing result of [div_mod 5 2]*)let _ = print_int_pair (div_mod 5 2)