What a tuple is
Some values belong together. A pet has a name and an age. A point has an x and a y. A tuple keeps a few values like these in one variable, written in parentheses:
val pet = ("Rex", 4)
println(pet._1)
println(pet._2)
Rex
4
The type of pet is (String, Int). Each position has its own type, so a tuple can mix strings, numbers and anything else. The values are read with ._1 for the first and ._2 for the second. They count from 1, not from 0, which is different from ArrayBuffer indexes.
Unpacking
Writing pet._1 everywhere is hard to read. You can unpack the tuple into named values instead:
val (name, age) = pet
println(s"$name $age")
Rex 4
The names go in the same order as the values. The same pattern is what for ((name, points) <- scores) uses to unpack each pair in a loop. If the pattern has a different number of names than the tuple has values, the compiler rejects it. For a (String, Int) pair, a pattern with three names is a compile error, so the mistake shows up before the program runs.
Returning two values
A function returns one value, but that value can be a tuple. The return type is the tuple's type, such as (Int, Int):
def splitTime(minutes: Int): (Int, Int) = {
return (minutes / 60, minutes % 60)
}
Integer division gives the whole hours, and % gives the minutes left. splitTime(135) returns (2,15), and splitTime(59) returns (0,59). The caller can unpack the result straight away: val (hours, mins) = splitTime(135).
More than two values
A tuple can hold more than two values. val (a, b, c) = ("Rex", 4, true) works, and println(s"$a $b $c") prints Rex 4 true. The third value is ._3. Tuples are best for a few values that travel together briefly, such as a function's result. When a group of values has a meaning of its own, a class with named fields is easier to read than ._1 and ._2.
Tuples can't change
A tuple's values are fixed. This line does not compile:
pet._2 = 5
The compiler reports Reassignment to val _2. To get a different age, build a new tuple. (pet._1, 5) prints as (Rex,5), and pet itself stays (Rex,4).
Printing a tuple shows its values in parentheses with a comma between them and no space, like (Rex,4).
The exercise
The task has three parts. First, make splitTime return its tuple. Next, unpack pet into name and age. Last, call splitTime(135) and unpack the result into hours and mins. Here is the finished code:
class Solution {
def splitTime(minutes: Int): (Int, Int) = {
return (minutes / 60, minutes % 60)
}
def mainFunction(): Unit = {
val pet = ("Rex", 4)
println(pet._1)
val (name, age) = pet
println(s"$name is $age")
val (hours, mins) = splitTime(135)
println(s"$name walked $hours h $mins min")
}
}
It prints:
Rex
Rex is 4
Rex walked 2 h 15 min
Each println uses names that the unpacking line above it creates, so every unpacking has to come before the line that prints those names. The last line also reuses name from the first unpacking.
Common mistakes
- Counting from 0:
pet._0doesn't exist. The first value is._1. - Swapping names when unpacking:
val (age, name) = petgivesagethe string"Rex"andnamethe number 4. - Trying to assign to
._2. Build a new tuple instead.
Key takeaways
- A tuple groups a few values of possibly different types:
("Rex", 4)has type(String, Int). - Read values with
._1,._2, or unpack them withval (a, b) = tuple. - A function returns several values by returning a tuple.
- Tuples can't be changed; make a new one.
