# 4. Advanced Control Flow Written by Matt Galloway

In the previous chapter, you learned how to control the flow of execution using the decision-making powers of `if` statements and the `while` loop. In this chapter, you’ll continue to learn how to control the flow of execution. You’ll learn about another loop known as the `for` loop.

Loops may not sound very interesting, but they’re very common in computer programs. For example, you might have code to download an image from the cloud; with a loop, you could run that multiple times to download your entire photo library. Or if you have a game with multiple computer-controlled characters, you might need a loop to go through each one and make sure it knows what to do next.

You’ll also learn about `switch` statements, which are particularly powerful in Swift. They let you inspect a value and decide what to do based on that value. They’re incredibly powerful when used with some advanced Swift features such as pattern matching.

## Countable ranges

Before you dive into the `for` loop statement, you need to know about the Countable Range data types, which let you represent a sequence of countable integers. Let’s look at two types of ranges.

First, there’s countable closed range, which you represent like so:

``````let closedRange = 0...5
``````

The three dots (`...`) indicate that this range is closed, which means the range goes from 0 to 5 inclusive. That’s the numbers `(0, 1, 2, 3, 4, 5)`.

Second, there’s countable half-open range, which you represent like so:

``````let halfOpenRange = 0..<5
``````

Here, you replace the three dots with two dots and a less-than sign (`..<`). Half-open means the range goes from 0 up to, but not including, 5. That’s the numbers `(0, 1, 2, 3, 4)`.

Both open and half-open ranges must always be increasing. In other words, the second number must always be greater than or equal to the first. Countable ranges are commonly used in both `for` loops and `switch` statements, which means that throughout the rest of the chapter, you’ll use ranges as well!

### A random interlude

A common need in programming is to be able to generate random numbers. And Swift provides the functionality built in to the language, which is pretty handy!

``````while Int.random(in: 1...6) != 6 {
print("Not a six")
}
``````

## For loops

In the previous chapter you looked at `while` loops. Now that you know about ranges, it’s time to look at another type of loop: the `for` loop. This is probably the most common loop you’ll see, and you’ll use it to run code a certain number of times.

``````for <CONSTANT> in <COUNTABLE RANGE> {
<LOOP CODE>
}
``````
``````let count = 10
var sum = 0
for i in 1...count {
sum += i
}
``````

``````sum = 1
var lastSum = 0

for _ in 0..<count {
let temp = sum
sum = sum + lastSum
lastSum = temp
}
``````
``````sum = 0
for i in 1...count where i % 2 == 1 {
sum += i
}
``````

### Continue and labeled statements

Sometimes you’d like to skip a loop iteration for a particular case without breaking out of the loop entirely. You can do this with the `continue` statement, which immediately ends the current iteration of the loop and starts the next iteration.

``````sum = 0

for row in 0..<8 {
if row % 2 == 0 {
continue
}

for column in 0..<8 {
sum += row * column
}
}
``````

``````sum = 0

rowLoop: for row in 0..<8 {
columnLoop: for column in 0..<8 {
if row == column {
continue rowLoop
}
sum += row * column
}
}
``````

### Mini-exercises

``````sum = 0
for row in 0..<8 {
if row % 2 == 0 {
continue
}
for column in 0..<8 {
sum += row * column
}
}
``````

## Switch statements

You can also control flow via the `switch` statement. It executes different code depending on the value of a variable or constant. Here’s a `switch` statement that acts on an integer:

``````let number = 10

switch number {
case 0:
print("Zero")
default:
print("Non-zero")
}
``````
``````switch number {
case 10:
print("It’s ten!")
default:
break
}
``````
``````let string = "Dog"

switch string {
case "Cat", "Dog":
print("Animal is a house pet.")
default:
print("Animal is not a house pet.")
}
``````

You can also give your `switch` statements more than one case. In the previous chapter, you saw an `if` statement that used multiple `else` clauses to convert an hour of the day to a string describing that part of the day. You could rewrite that more succinctly with a `switch` statement, like so:

``````let hourOfDay = 12
var timeOfDay = ""

switch hourOfDay {
case 0, 1, 2, 3, 4, 5:
timeOfDay = "Early morning"
case 6, 7, 8, 9, 10, 11:
timeOfDay = "Morning"
case 12, 13, 14, 15, 16:
timeOfDay = "Afternoon"
case 17, 18, 19:
timeOfDay = "Evening"
case 20, 21, 22, 23:
timeOfDay = "Late evening"
default:
timeOfDay = "INVALID HOUR!"
}

print(timeOfDay)
``````
``````switch hourOfDay {
case 0...5:
timeOfDay = "Early morning"
case 6...11:
timeOfDay = "Morning"
case 12...16:
timeOfDay = "Afternoon"
case 17...19:
timeOfDay = "Evening"
case 20..<24:
timeOfDay = "Late evening"
default:
timeOfDay = "INVALID HOUR!"
}
``````
``````switch number {
case let x where x % 2 == 0:
print("Even")
default:
print("Odd")
}
``````
``````switch number {
case _ where number % 2 == 0:
print("Even")
default:
print("Odd")
}
``````

### Partial matching

Another way you can use `switch` statements with matching to great effect is as follows:

``````let coordinates = (x: 3, y: 2, z: 5)

switch coordinates {
case (0, 0, 0): // 1
print("Origin")
case (_, 0, 0): // 2
print("On the x-axis.")
case (0, _, 0): // 3
print("On the y-axis.")
case (0, 0, _): // 4
print("On the z-axis.")
default:        // 5
print("Somewhere in space")
}
``````
``````switch coordinates {
case (0, 0, 0):
print("Origin")
case (let x, 0, 0):
print("On the x-axis at x = \(x)")
case (0, let y, 0):
print("On the y-axis at y = \(y)")
case (0, 0, let z):
print("On the z-axis at z = \(z)")
case let (x, y, z):
print("Somewhere in space at x = \(x), y = \(y), z = \(z)")
}
``````
``````switch coordinates {
case let (x, y, _) where y == x:
print("Along the y = x line.")
case let (x, y, _) where y == x * x:
print("Along the y = x^2 line.")
default:
break
}
``````

## Challenges

Before moving on, here are some challenges to test your knowledge of advanced control flow. It is best if you try to solve them yourself, but solutions are available if you get stuck. These came with the download or are available at the printed book’s source code link listed in the introduction.

### Challenge 1: How many times

In the following `for` loop, what will be the value of `sum`, and how many iterations will happen?

``````var sum = 0
for i in 0...5 {
sum += i
}
``````

### Challenge 2: Count the letter

In the `while` loop below, how many instances of “a” will there be in `aLotOfAs`? Hint: `aLotOfAs.count` tells you how many characters are in the string `aLotOfAs`.

``````var aLotOfAs = ""
while aLotOfAs.count < 10 {
aLotOfAs += "a"
}
``````

### Challenge 3: What will print

Consider the following `switch` statement:

``````switch coordinates {
case let (x, y, z) where x == y && y == z:
print("x = y = z")
case (_, _, 0):
print("On the x/y plane")
case (_, 0, _):
print("On the x/z plane")
case (0, _, _):
print("On the y/z plane")
default:
print("Nothing special")
}
``````
``````let coordinates = (1, 5, 0)
let coordinates = (2, 2, 2)
let coordinates = (3, 0, 1)
let coordinates = (3, 2, 5)
let coordinates = (0, 2, 4)
``````

### Challenge 4: Closed range size

A closed range can never be empty. Why?

### Challenge 5: The final countdown

Print a countdown from 10 to 0. (Note: do not use the `reversed()` method, which will be introduced later.)

### Challenge 6: Print a sequence

Print 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0. (Note: do not use the `stride(from:by:to:)` function, which will be introduced later.)

## Key points

• You can use countable ranges to create a sequence of integers, incrementing to move from one value to another.
• Closed ranges include both the start and end values.
• Half-open ranges include the start value and stop one before the end value.
• For loops allow you to iterate over a range.
• The continue statement lets you finish the current iteration of a loop and begin the next iteration.
• Labeled statements let you use `break` and `continue` on an outer loop.
• You use switch statements to decide which code to run depending on the value of a variable or constant.
• The power of a `switch` statement comes from leveraging pattern matching to compare values using complex rules.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.