Skip to content
Theory · Functions · lesson 4 of 9

Several results

In the operators theme, sweets were shared like this: / tells how many each child gets, and % tells how many sweets are left over. These are two answers to one question, and it is handy to get both from one function. But until now there was one type after ->, and return handed back one value.

Picture the food processor handing out not one glass but a tray with two: one is marked "each", the other "left over". You carry the tray in one move, and drink from each glass separately. In Swift such a tray is called a tuple:

SWIFT
func share(_ sweets: Int, by kids: Int) -> (each: Int, left: Int) {
    (sweets / kids, sweets % kids)
}

let result = share(17, by: 5)
print(result.each) // 3
print(result.left) // 2
print(result) // (each: 3, left: 2)

Let's go through the program:

  1. -> (each: Int, left: Int) promises that the function returns two integers named each and left.
  2. The body is a single expression: two values in parentheses, separated by a comma.
  3. share(17, by: 5) returns 3 and 2 together, and both numbers are in result.
  4. result.each and result.left get them by name.
  5. print(result) prints the whole tuple, along with the names of its parts.

The tuple

A tuple is several values gathered into one. They are written in parentheses, separated by commas: (3, 2).

A tuple's type is written the same way, in parentheses: (each: Int, left: Int). The names of the parts are optional: (Int, Int) is also a tuple of two integers. The parts can be of different types too: ("Anna", 30) is a tuple of a string and a number.

Swift's standard library, the ready-made types and functions installed together with the language, like Int and print, does the same. For example, 17.quotientAndRemainder(dividingBy: 5) returns the tuple (quotient: 3, remainder: 2), the quotient and the remainder together.

Junior interviews ask: how do you return several values from a function? The short answer is a tuple. The result type goes in parentheses, -> (each: Int, left: Int), and the values themselves are listed with commas, in parentheses too.

Getting the parts out

There are four ways to get at the parts of a tuple. You have already seen access by name, and the other three are in this example:

SWIFT
print(result.0, result.1) // 3 2
let (perKid, leftover) = share(20, by: 3)
print(perKid, leftover) // 6 2
let (whole, _) = share(9, by: 2)
print(whole) // 4

By name

result.each is the part's name after a dot. The compiler checks names: for result.rest it answers value of tuple type '(each: Int, left: Int)' has no member 'rest'.

By number

result.0 and result.1 are the part's number after a dot. Parts are numbered from zero. Numbers always work, even when the parts have no names, but code with names is easier to read.

Splitting into constants

let (perKid, leftover) = share(20, by: 3) declares two constants at once: the first part of the tuple goes into perKid, the second into leftover. The function returned (6, 2), and the program prints 6 2.

Skipping a part

If one of the parts is not needed, you write _ in its place, as in a loop where the number is not needed. In let (whole, _) = share(9, by: 2), whole gets 4, and the remainder 1 is not stored anywhere.

Here the tray picture is inaccurate. You can take the glasses off a tray in any order, and each keeps its own juice. But when splitting a tuple, Swift looks only at the order of the parts, not at their names.

Common mistake

A tuple was split into constants with the same names as in the result type, but in a different order:

SWIFT
let (left, each) = share(17, by: 5) // ✗
print(left, each) // 3 2

There is no error at compile time or at run time, but left got 3, and each got 2. The first part of a tuple always goes into the first constant. Swift does not compare the names each and left from the result type with the names of the constants. List the constants in the same order as the parts in the result type, or take the parts by name: result.left.

Key points

  • A tuple gathers several values into one: (3, 2), and with the result type (each: Int, left: Int) a function returns them together.
  • The parts of a tuple are taken by name, result.each, or by number from zero, result.0.
  • let (a, b) = … splits a tuple into constants, and _ skips a part you don't need.
  • Splitting goes by the order of the parts, not by their names.