Control Flow
Control flow is an important concept in programming. It allows you to control the flow of your program by making decisions and repeating actions. Without control flow, your program would execute in a linear fashion, which would greatly limit its capabilities.
In this chapter, we will explore the different control flow structures available in Glu, such as conditional statements and loops. Understanding these structures will help you write more complex and powerful programs.
Conditions
Conditional statements allow you to execute different blocks of code based on certain conditions. The most common conditional statement is the if
statement.
The if
, else
, and else if
Statements
The if
statement allows you to execute a block of code if a condition is true. Here is an example:
1
2
3
4
5
let x: Int = 10;
if x > 5 {
std::print("x is greater than 5");
}
In this example, the code inside the if
block will only be executed if the condition x > 5
is true, which is the case here.
You can also add an else
block to execute code when the condition is false:
1
2
3
4
5
6
7
let x: Int = 3;
if x > 5 {
std::print("x is greater than 5");
} else {
std::print("x is less than or equal to 5");
}
In this case, the code inside the else
block will be executed because the condition x > 5
is false.
You can also chain multiple conditions using else if
:
1
2
3
4
5
6
7
8
9
let age: Int = 18;
if age < 18 {
std::print("You are a minor");
} else if age < 21 {
std::print("You are a young adult");
} else {
std::print("You are an adult");
}
The Ternary Operator
The ternary operator is a shorthand way of writing an if
statement. It has the following syntax:
1
let result: Int = condition ? value_if_true: value_if_false;
Here is an example:
1
2
let x: Int = 10;
std::print(x > 5 ? "x is greater than 5" : "x is less than or equal to 5");
This code is equivalent to the following if
statement:
1
2
3
4
5
6
7
8
let x: Int = 10;
var message: String;
if x > 5 {
message = "x is greater than 5";
} else {
message = "x is less than or equal to 5";
}
std::print(message);
Loops
Loops allow you to repeat a block of code multiple times. There are two main types of loops in Glu: for
loops and while
loops.
The while
Loop
The while
loop repeats a block of code as long as a condition is true. Here is an example:
1
2
3
4
5
6
let count: Int = 0;
while count <= 5 {
std::print(count);
count = count + 1;
}
In this example, the loop will print the numbers from 0 to 5, inclusive.
The while
loop is useful when you don’t know in advance how many times you need to repeat a block of code. In this case, a for
loop might be more appropriate.
The for
Loop
The for
loop repeats a block of code a fixed number of times. Here is an example:
1
2
3
for i in 0...5 {
std::print(i);
}
This code is equivalent to the while
loop example above. The for
loop is more concise and easier to read when you know in advance how many times you need to repeat a block of code.
Here, i
is a variable that takes on the values from 0 to 5, inclusive. The ...
operator is used to create a range of values. The for
loop will iterate over each value in the range and execute the block of code.
You can also use the ..<
operator to create a range that excludes the upper bound:
1
2
3
for i in 0..<5 {
std::print(i);
}
In this case, the loop will print the numbers from 0 to 4.
There are other types of ranges, such as the infinite range 0...
, which starts at 0 and goes to infinity:
1
2
3
for i in 0... {
std::print(i);
}
This infinite loop will print the numbers from 0 to the maximum value of an Int
.
For loops can also iterate over arrays and other collections, not just ranges:
1
2
3
4
5
let numbers: Int[5] = { 1, 2, 3, 4, 5 };
for n in numbers {
std::print(n);
}
In this example, the loop will print the numbers from the numbers
array: 1, 2, 3, 4, and 5.
The break
and continue
Statements
Within a loop, you can use the break
statement to exit the loop early:
1
2
3
4
5
6
for i in 0... {
if i > 5 {
break;
}
std::print(i);
}
In this example, the loop will print the numbers from 0 to 5 and then break out of the loop.
You can also use the continue
statement to skip the rest of the current iteration and continue with the next one:
1
2
3
4
5
6
for i in 0...5 {
if i % 2 == 0 {
continue;
}
std::print(i);
}
In this example, even numbers will be skipped, and only odd numbers between 0 and 5 inclusive will be printed: 1, 3, and 5.
Nested Loops
You can nest loops inside each other to create more complex patterns. Here is an example of a nested loop:
1
2
3
4
5
6
for i in 0...2 {
for j in 0...2 {
std::printout("*");
}
std::print("");
}
This code will print the following pattern:
1
2
3
***
***
***
In this example, the outer loop iterates over the rows, and the inner loop iterates over the columns. The std::printout
function is used to print characters without a newline at the end, and std::print
is used to print a newline at the end of each row.
Recursion
Recursion is an alternative to loops, where code can be repeated by calling a function from within itself. Here is an example of a recursive function that prints a number by printing each digit separately:
1
2
3
4
5
6
7
8
9
10
11
12
func printNumber(n: Int) {
if n < 10 {
std::printout(n);
} else {
printNumber(n / 10);
std::printout(n % 10);
}
}
func main() {
printNumber(123);
}
In this example, the printNumber
function prints the number 123
by recursively calling itself with the number divided by 10 until the number is less than 10. Here is what happens at each step:
main
callsprintNumber(123)
.printNumber(123)
callsprintNumber(123 / 10)
which isprintNumber(12)
.printNumber(12)
callsprintNumber(12 / 10)
which isprintNumber(1)
.printNumber(1)
prints1
as it is less than 10.
printNumber(12)
prints12 % 10
which is2
.
printNumber(123)
prints123 % 10
which is3
.
This very simple function demonstrates the power of recursion in solving seemingly complex problems. Recursion is a powerful tool that can be difficult to understand at first but can lead to elegant and concise solutions to many problems. However, it can also be less efficient than using loops, so it should be used judiciously.
When using recursion, always make sure that the base case (the condition that stops the recursion) is always reached, to avoid infinite recursion, which can lead to a stack overflow and crash your program. In the example above, the base case is when n < 10
, in which case the function does not call itself recursively.
Conclusion
Control flow structures are essential for writing complex programs. By using conditional statements, loops, and recursion, you can create programs that make decisions, repeat actions, and solve problems in an elegant and efficient way. Understanding these structures will help you become a better programmer and write more powerful and flexible code.