# 4 Control Flow Written by Jonathan Sande & Matt Galloway

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

When writing a computer program, you need to be able to tell the computer what to do in different scenarios. For example, a calculator app would need to perform one action if the user taps the addition button, and another action if the user taps the subtraction button.

In computer programming terms, this concept is known as control flow, because you can control the flow of decisions the code makes at multiple points. In this chapter, youâ€™ll learn how to make decisions and repeat tasks in your programs.

## Making comparisons

Youâ€™ve already encountered a few different Dart types, such as `int`, `double` and `String`. Each of those types is a data structure which is designed to hold a particular type of data. The `int` type is for whole numbers while the `double` type is for decimal numbers. `String`, by comparison, is useful for storing textual information.

A new way of structuring information, though, requires a new data type. Consider the answers to the following questions:

• Is the door open?
• Do pigs fly?
• Is that the same shirt you were wearing yesterday?
• Is the traffic light red?
• Are you older than your grandmother?
• Does this make me look fat?

These are all yes-no questions. If you want to store the answers in a variable, you could use strings like `'yes'` and `'no'`. You could even use integers where `0` means no and `1` means yes. The problem with that, though, is what happens when you get `42` or `'celery'`? It would be better to avoid any ambiguity and have a type in which the only possible values are `yes` and `no`.

### Boolean values

Dart has a data type just for this. Itâ€™s called `bool`, which is short for Boolean. A Boolean value can have one of two states. While in general you could refer to the states as yes and no, on and off, or 1 and 0, most programming languages, Dart included, call them true and false.

``````const bool yes = true;
const bool no = false;
``````
``````const yes = true;
const no = false;
``````

### Boolean operators

Booleans are commonly used to compare values. For example, you may have two values and you want to know if theyâ€™re equal. Either they are equal, which would be `true`, or they arenâ€™t equal, which would be `false`.

#### Testing equality

You can test for equality using the equality operator, which is denoted by `==`, that is, two equals signs.

``````const doesOneEqualTwo = (1 == 2);
``````
``````print(doesOneEqualTwo);
``````
``````const doesOneEqualTwo = 1 == 2;
``````

#### Testing inequality

You can also find out if two values are not equal using the `!=` operator:

``````const doesOneNotEqualTwo = (1 != 2);
``````
``````const alsoTrue = !(1 == 2);
``````

#### Testing greater and less than

There are two other operators to help you compare two values and determine if a value is greater than (`>`) or less than (`<`) another value. You know these from mathematics:

``````const isOneGreaterThanTwo = (1 > 2);
const isOneLessThanTwo = (1 < 2);
``````
``````print(1 <= 2); // true
print(2 <= 2); // true
``````
``````print(2 >= 1); // true
print(2 >= 2); // true
``````

### Boolean logic

Each of the examples above tests just one condition. When George Boole invented the Boolean, he had much more planned for it than these humble beginnings. He invented Boolean logic, which lets you combine multiple conditions to form a result.

#### AND operator

Ray would like to go cycling in the park with Vicki this weekend. Itâ€™s a little uncertain whether they can go, though. Thereâ€™s a chance that it might rain. Also, Vicky says she canâ€™t go unless she finishes up the art project sheâ€™s working on. So Ray and Vicki will go cycling in the park if itâ€™s sunny and Vicki finishes her work.

``````const isSunny = true;
const isFinished = true;
const willGoCycling = isSunny && isFinished;
``````

#### OR operator

Vicki would like to draw a platypus, but she needs a model. She could either travel to Australia or she could find a photograph on the internet. If only one of two conditions need to be true in order for the result to be true, this is an example of a Boolean OR operation. The only instance where the result would be false is if both input Booleans were false. If Vicki doesnâ€™t go to Australia and she also doesnâ€™t find a photograph on the internet, then she wonâ€™t draw a platypus.

``````const willTravelToAustralia = true;
const canFindPhoto = false;
const canDrawPlatypus = willTravelToAustralia || canFindPhoto;
``````

#### Operator precedence

As was the case in the Ray and Vicki examples above, Boolean logic is usually applied to multiple conditions. When you want to determine if two conditions are true, you use AND, while if you only care whether one of the two conditions is true, you use OR.

``````const andTrue = 1 < 2 && 4 > 3;
const andFalse = 1 < 2 && 3 > 4;
const orTrue = 1 < 2 || 3 > 4;
const orFalse = 1 == 2 || 3 == 4;
``````
``````3 > 4 && 1 < 2 || 1 < 4
``````
``````false && true || true
``````

``````false && true || true
``````

#### Overriding precedence with parentheses

If you want to override the default operator precedence, you can put parentheses around the parts Dart should evaluate first.

``````3 > 4 && (1 < 2 || 1 < 4)  // false
(3 > 4 && 1 < 2) || 1 < 4  // true
``````

### String equality

Sometimes youâ€™ll want to determine if two strings are equal. For example, a childrenâ€™s game of naming an animal in a photo would need to determine if the player answered correctly.

``````const guess = 'dog';
const dogEqualsCat = guess == 'cat';
``````

### Mini-exercises

1. Create a constant called `myAge` and set it to your age. Then, create a constant named `isTeenager` that uses Boolean logic to determine if the age denotes someone in the age range of 13 to 19.
2. Create another constant named `maryAge` and set it to `30`. Then, create a constant named `bothTeenagers` that uses Boolean logic to determine if both you and Mary are teenagers.
3. Create a `String` constant named `reader` and set it to your name. Create another `String` constant named `ray` and set it to `'Ray Wenderlich'`. Create a Boolean constant named `rayIsReader` that uses string equality to determine if `reader` and `ray` are equal.

## The if statement

The first and most common way of controlling the flow of a program is through the use of an `if` statement, which allows the program to do something only if a certain condition is true. For example, consider the following:

``````if (2 > 1) {
print('Yes, 2 is greater than 1.');
}
``````
``````Yes, 2 is greater than 1.
``````

### The else clause

You can extend an `if` statement to provide code to run in the event that the condition turns out to be `false`. This is known as the `else` clause.

``````const animal = 'Fox';
if (animal == 'Cat' || animal == 'Dog') {
print('Animal is a house pet.');
} else {
print('Animal is not a house pet.');
}
``````
``````Animal is not a house pet.
``````

### Else-if chains

You can go even further with `if` statements. Sometimes you want to check one condition, and then check another condition if the first condition isnâ€™t true. This is where `else-if` comes into play, nesting another `if` statement in the `else` clause of a previous `if` statement.

``````const trafficLight = 'yellow';
var command = '';
if (trafficLight == 'red') {
command = 'Stop';
} else if (trafficLight == 'yellow') {
command = 'Slow down';
} else if (trafficLight == 'green') {
command = 'Go';
} else {
command = 'INVALID COLOR!';
}
print(command);
``````
``````Slow down
``````

### Variable scope

`if` statements introduce a new concept called scope. Scope is the extent to which a variable can be seen throughout your code. Dart uses curly braces as the boundary markers in determining a variableâ€™s scope. If you define a variable inside a pair of curly braces, then youâ€™re not allowed to use that variable outside of those braces.

``````const global = 'Hello, world';

void main() {
const local = 'Hello, main';

if (2 > 1) {
const insideIf = 'Hello, anybody?';

print(global);
print(local);
print(insideIf);
}

print(global);
print(local);
print(insideIf); // Not allowed!
}
``````
``````Undefined name 'insideIf'.
``````

### The ternary conditional operator

Youâ€™ve worked with operators that have two operands. For example, in `(myAge > 16)`, the two operands are `myAge` and `16`. But thereâ€™s also an operator that takes three operands: the ternary conditional operator. Itâ€™s strangely related to `if` statements â€” youâ€™ll see why this is in just a bit.

``````const score = 83;

String message;
if (score >= 60) {
message = 'You passed';
} else {
message = 'You failed';
}
``````
``````(condition) ? valueIfTrue : valueIfFalse;
``````
``````const score = 83;
const message = (score >= 60) ? 'You passed' : 'You failed';
``````

### Mini-exercises

1. Create a constant named `myAge` and initialize it with your age. Write an `if` statement to print out â€śTeenagerâ€ť if your age is between `13` and `19`, and â€śNot a teenagerâ€ť if your age is not between `13` and `19`.
2. Use a ternary conditional operator to replace the `else-if` statement that you used above. Set the result to a variable named `answer`.

## Switch statements

An alternate way to handle control flow, especially for multiple conditions, is with a `switch` statement. The `switch` statement takes the following form:

``````switch (variable) {
case value1:
// code
break;
case value2:
// code
break;

...

default:
// code
}
``````

### Replacing else-if chains

Using `if` statements are convenient when you have one or two conditions, but the syntax can be a little verbose when you have a lot of conditions. Check out the following example:

``````const number = 3;
if (number == 0) {
print('zero');
} else if (number == 1) {
print('one');
} else if (number == 2) {
print('two');
} else if (number == 3) {
print('three');
} else if (number == 4) {
print('four');
} else {
print('something else');
}
``````
``````const number = 3;
switch (number) {
case 0:
print('zero');
break;
case 1:
print('one');
break;
case 2:
print('two');
break;
case 3:
print('three');
break;
case 4:
print('four');
break;
default:
print('something else');
}
``````

### Switching on strings

A `switch` statement also works with strings. Try the following example:

``````const weather = 'cloudy';
switch (weather) {
case 'sunny':
print('Put on sunscreen.');
break;
case 'snowy':
break;
case 'cloudy':
case 'rainy':
print('Bring an umbrella.');
break;
default:
print("I'm not familiar with that weather.");
}
``````
``````Bring an umbrella.
``````

### Enumerated types

Enumerated types, also known as enums, play especially well with `switch` statements. You can use them to define your own type with a finite number of options.

``````const weather = 'I like turtles.';
``````
``````enum Weather {
sunny,
snowy,
cloudy,
rainy,
}
``````

#### Naming enums

When creating an `enum` in Dart, itâ€™s customary to write the `enum` name with an initial capital letter, as `Weather` was written in the example above. The values of an enum should use `lowerCamelCase` unless you have a special reason to do otherwise.

### Switching on enums

Now that you have the `enum` defined, you can use a `switch` statement to handle all the possibilities, like so:

``````const weatherToday = Weather.cloudy;
switch (weatherToday) {
case Weather.sunny:
print('Put on sunscreen.');
break;
case Weather.snowy:
break;
case Weather.cloudy:
case Weather.rainy:
print('Bring an umbrella.');
break;
}
``````
``````Bring an umbrella.
``````

#### Enum values and indexes

Before leaving the topic of enums, thereâ€™s one more thing to note. If you try to print an enum, youâ€™ll get its value:

``````print(weatherToday);
// Weather.cloudy
``````
``````final index = weatherToday.index;
``````

### Avoiding the overuse of switch statements

Switch statements, or long `else-if` chains, can be a convenient way to handle a long list of conditions. If youâ€™re a beginning programmer, go ahead and use them; theyâ€™re easy to use and understand.

### Mini-exercises

1. Make an `enum` called `AudioState` and give it values to represent `playing`, `paused` and `stopped` states.
2. Create a constant called `audioState` and give it an `AudioState` value. Write a `switch` statement that prints a message based on the value.

## Loops

In the first three chapters of this book, your code ran from the top of the `main` function to the bottom, and then it was finished. With the addition of `if` statements in this chapter, you gave your code the opportunity to make decisions. However, itâ€™s still running from top to bottom, albeit following different branches.

### While loops

A while loop repeats a block of code as long as a Boolean condition is true. You create a while loop like so:

``````while (condition) {
// loop code
}
``````
``````while (true) { }
``````
``````var sum = 1;
while (sum < 10) {
sum += 4;
print(sum);
}
``````

### Do-while loops

A variant of the `while` loop is called the `do-while` loop. It differs from the `while` loop in that the condition is evaluated at the end of the loop rather than at the beginning. Thus, the body of a `do-while` loop is always executed at least once.

``````do {
// loop code
} while (condition)
``````
``````sum = 1;
do {
sum += 4;
print(sum);
} while (sum < 10);
``````

### Comparing while and do-while loops

It isnâ€™t always the case that `while` loops and `do-while` loops will give the same result. For example, hereâ€™s a `while` loop where `sum` starts at `11`:

``````sum = 11;
while (sum < 10) {
sum += 4;
}
print(sum);
``````
``````sum = 11;
do {
sum += 4;
} while (sum < 10);
print(sum);
``````

### Breaking out of a loop

Sometimes youâ€™ll need to break out of a loop early. You can do this using the `break` statement, just as you did from inside the `switch` statement earlier. This immediately stops the execution of the loop and continues on to the code that follows the loop.

``````sum = 1;
while (true) {
sum += 4;
if (sum > 10) {
break;
}
}
``````

### A random interlude

A common need in programming is to be able to generate random numbers. And Dart provides this functionality in the `dart:math` library, which is pretty handy!

``````import 'dart:math';
``````
``````final random = Random();
while (random.nextInt(6) + 1 != 6) {
print('Not a six!');
}
print('Finally, you got a six!');
``````
``````Not a six!
Not a six!
Finally, you got a six!
``````

### For loops

In addition to `while` loops, Dart has another type of loop called a `for` loop. This is probably the most common loop youâ€™ll see, and you use it to run a block of code a set number of times. In this section youâ€™ll learn about C-style `for` loops, and in the next section, about `for-in` loops.

``````for (var i = 0; i < 5; i++) {
print(i);
}
``````
``````0
1
2
3
4
``````

#### The continue keyword

Sometimes you want to skip an iteration only for a certain condition. You can do that using the `continue` keyword. Have a look at the following example:

``````for (var i = 0; i < 5; i++) {
if (i == 2) {
continue;
}
print(i);
}
``````
``````0
1
3
4
``````

### For-in loops

Thereâ€™s another type of `for` loop that has simpler syntax; itâ€™s called a `for-in` loop. It doesnâ€™t have any sort of index or counter variable associated with it, but it makes iterating over a collection very convenient.

``````const myString = 'I âť¤ Dart';

for (var codePoint in myString.runes) {
print(String.fromCharCode(codePoint));
}
``````
``````I

âť¤

D
a
r
t
``````

### For-each loops

You can sometimes simplify `for-in` loops even more with the `forEach` method that is available to collections.

``````const myNumbers = [1, 2, 3];
``````
``````myNumbers.forEach((number) => print(number));
``````
``````myNumbers.forEach((number) {
print(number);
});
``````
``````1
2
3
``````

### Mini-exercises

1. Create a variable named `counter` and set it equal to `0`. Create a `while` loop with the condition `counter < 10`. The loop body should print out â€ścounter is Xâ€ť (where X is replaced with the value of `counter`) and then increment `counter` by 1.
2. Write a `for` loop starting at `1` and ending with `10` inclusive. Print the square of each number.
3. Write a `for-in` loop to iterate over the following collection of numbers. Print the square root of each number.
``````const numbers = [1, 2, 4, 7];
``````

## Challenges

Before moving on, here are some challenges to test your knowledge of control flow. Itâ€™s best if you try to solve them yourself, but solutions are available in the `challenge` folder if you get stuck.

### Challenge 1: Find the error

Whatâ€™s wrong with the following code?

``````const firstName = 'Bob';
if (firstName == 'Bob') {
const lastName = 'Smith';
} else if (firstName == 'Ray') {
const lastName = 'Wenderlich';
}
final fullName = firstName + ' ' + lastName;
``````

### Challenge 2: Boolean challenge

In each of the following statements, what is the value of the Boolean expression?

``````true && true
false || false
(true && 1 != 2) || (4 > 3 && 100 < 1)
((10 / 2) > 3) && ((10 % 2) == 0)
``````

### Challenge 3: Next power of two

Given a number, determine the next power of two above or equal to that number. Powers of two are the numbers in the sequence of 2Âą, 2Â˛, 2Âł, and so on. You may also recognize the series as 1, 2, 4, 8, 16, 32, 64â€¦

### Challenge 4: Fibonacci

Calculate the nth Fibonacci number. The Fibonacci sequence starts with 1, then 1 again, and then all subsequent numbers in the sequence are simply the previous two values in the sequence added together (1, 1, 2, 3, 5, 8â€¦). You can get a refresher here: https://en.wikipedia.org/wiki/Fibonacci_number

### Challenge 5: 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 (var i = 0; i <= 5; i++) {
sum += i;
}
``````

### Challenge 6: The final countdown

Print a countdown from 10 to 0.

### Challenge 7: Print a sequence

Print the sequence `0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0`.

## Key points

• You use the Boolean data type `bool` to represent `true` and `false`.
• The comparison operators, all of which return a Boolean, are:

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.