What a tuple is
Some values belong together: a movie has a title and a year, a point has an x and a y. A tuple keeps a few such values in one constant or variable. You write them in parentheses, separated by commas:
let movie = (title: "Frozen", year: 2013)
print(movie.title)
print(movie.1)
Frozen
2013
The type of movie is (title: String, year: Int). The parts can have different types, and the labels are optional. A part is read by its label (movie.title) or by its position, counting from 0 (movie.0, movie.1).
Unpacking a tuple
Instead of reading parts one at a time, you can unpack the whole tuple into new constants. The names go in parentheses, in the same order as the parts:
let (title, year) = movie
print("\(title) \(year)")
Frozen 2013
This is the same unpacking that for (i, item) in ... loops do later in this chapter. The number of names must match the number of parts. Unpacking movie into three names is a compile error, because the tuple has two parts. If you need only one part, write _ for the other: let (_, year) = movie.
Returning a tuple from a function
A function can only return one value, but that value can be a tuple. The return type is the tuple's type, and the labels are part of it. This is why the lesson's return (minutes / 60, minutes % 60) doesn't repeat the labels: the return type (hours: Int, mins: Int) already gives them. The caller either unpacks the result or reads a part by its label:
let (hours, mins) = splitTime(135)
print(splitTime(135).hours)
With 135 minutes, hours is 2 and mins is 15; the second line prints 2.
Constants and variables
A tuple stored with let can't change. Assigning movie.year = 2014 fails with "cannot assign to property: 'movie' is a 'let' constant". If the tuple is stored with var, the assignment works, and it changes only that copy: a tuple is a value type, so var other = movie makes an independent copy. A tuple never gets more parts, and each part keeps its type.
The lesson's exercise
- Return the tuple from
splitTime. The whole hours areminutes / 60(integer division drops the remainder), and the minutes left areminutes % 60. - Unpack
petintonameandagewithlet (name, age) = pet. The name comes first because it is the first part. - Unpack the result of
splitTime(135)intohoursandminsthe same way. A function result unpacks just like a stored tuple.
class Solution {
func splitTime(_ minutes: Int) -> (hours: Int, mins: Int) {
return (minutes / 60, minutes % 60)
}
func mainFunction() {
let pet = (name: "Rex", age: 4)
print(pet.name)
let (name, age) = pet
print("\(name) is \(age)")
let (hours, mins) = splitTime(135)
print("\(name) walked \(hours) h \(mins) min")
}
}
It prints:
Rex
Rex is 4
Rex walked 2 h 15 min
Common mistakes
- Names in the wrong order. Unpacking matches by position, not by name.
let (age, name) = petcompiles, butagenow holds "Rex" andnameholds 4, so the line prints4 is Rex. - Mixing up the two operators.
/gives the whole hours and%the minutes left. For 59 minutes,splitTime(59)gives(hours: 0, mins: 59). - Counting from 1.
movie.0is the title; there is nomovie.2on a two-part tuple.
Key takeaways
- A tuple groups a fixed number of values, possibly of different types, with optional labels.
- Read parts with
.labelor.0,.1, or unpack them withlet (a, b) = tuple. - A function returns several values by returning a tuple; the return type supplies the labels.
- A
lettuple can't be changed; avartuple can, but its shape stays fixed.
