This lesson we will learn more about flow control of a program. In the previous lesson, we built very simple programs that have one path of execution -- there was no variance based on any input. These kinds of programs are pretty uninteresting, as they always do the same thing every time.
But most programs are going to need to make decisions. Think of a computer game. It might load to a menu, but doesn't just complete unless you use controls to move a character around, or perform actions. How does the program know to do something based on your input? This requires using flow control and branching.
Before we get into the code, I want to introduce comments. Comments are notes that are for you, the programmer. The computer and compiler ignore them completely when building or executing your code.
Another use for comments is "commenting out code", which means you turn code into a comment so it doesn't get run. This is useful for testing or debugging, or simply leaving behind code that is no longer used, but you don't want to delete it.
D has three types of comments:
//
)and end at the end of the line. These are useful for short notes, or for temporarily disabling a line of code.
int x = 5; // declare x and set it to 5
/*
and end with the sequence */
. These are useful when you have a long note to write, or when you want to comment out multiple lines of code. Note that these cannot be nested, see the next comment type for nestable comments.
/* here are a bunch of notes that explain the thing
that I am about to do. These wouldn't fit on one line, so I put it
in a multiple-line comment. */
doTheThing();
/+
and end with the sequence +/
.
/+ Comment out the thing for now.
/+ here are a bunch of notes that explain the thing
that I am about to do. These wouldn't fit on one line, so I put it
in a multiple-line comment. +/
doTheThing();
+/
Computers are really good at doing math! If you wanted the computer to calculate the answer to 1 million math problems, it could do that and get all the answers right, in less than a second.
Before we talk about all the things we can do, we should note how to assign a new value to a variable. In D, this is done with the =
operator:
int x = 6; // assignment on declaration
x = 2; // reassignment
Having the computer calculate math is done by using pretty standard math operations. Just like in math, the computer can do addition and subtraction, multiplication and division, and exponentiation. However, some of the symbols and techniques we use in math are hard to type, so we have things that are equivalent in code. The following table describes how to do each operation:
Operation name | Mathematical Symbol | Equivalent code syntax | Example |
---|---|---|---|
Addition | + | + |
55 + 127 |
Subtraction | − | - |
150 - x |
Multiplication | × | * |
val * 5 |
Division | ÷ | / |
int half = value / 2 |
Exponentiation | Superscript, e.g. x² | ^^ |
x ^^ 2 |
D uses standard math operator precedence to perform operations. In math, and in D, the following things take precendence:
So the value of 5 + 4 * 3
is 17 both in math and in D. If you want to change the order to get the value 27, you can use parentheses: (5 + 4) * 3
.
D has 3 forms of branching. For this lesson we will be focusing only on the if
statement. An if
statement checks to see if some condition is true or false. If it is true, then the branch code executes. If it is false, the branch code does not execute.
if
statements can also be followed by an else
statement, which is code to execute when the branch is false. You do not need to include an else
statement, it is entirely optional.
if(true) {
writeln("the condition was true!");
}
else {
writeln("the condition was false!");
}
Like the int
type represents an integer, the bool
type represents a boolean. A boolean is a value that can be either true
or false
. In fact, like 42
is an int
, the symobls true
and false
are typed as bool
.
A condition is typically posing a question in the form of a boolean expression. The typical way to get a boolean value is to compare two values. We do this by using the Comparison operators.
Comparision operators are like math, but we use characters that are easy to type when building programs. The following table should help you type the correct operators:
Operation name | Mathematical Symbol | Equivalent code syntax | Example |
---|---|---|---|
Less Than | < | < |
var < 42 |
Greater Than | > | > |
x > 42 |
Equal | = | == |
word == "hello" |
Not Equal | ≠ | != |
result != "bad value" |
Less Than or Equal | ≤ | <= |
length <= 5 |
Greater Than or Equal | ≥ | >= |
units >= 100 |
One important thing to note here is that comparing two things as equal uses two equal signs, not one. This is because one equal sign is considered to be assignment! The compiler will complain if you try to use one equal sign inside a condition for an if
statement
Let's say we want to print the text "Value is too big!" if the variable dayOfYear
is bigger than or equal to 366
. The code would look like this:
if(dayOfYear >= 366) {
writeln("Value is too big!");
}
What if we wanted to check if a command is equal to "exit", and if so, write "Exiting!" and return from the main
function?
if(command == "exit") {
writeln("Exiting!");
return; // this returns from a function
}
Boolean logic is the practice of combining different conditions to get one final condition. In code, we have 3 major operations that can accomplish this, and we can use parentheses to clarify which order things should be checked. The three operations are:
Name and effect | Code syntax | Example |
---|---|---|
AND: true if both sides are true, otherwise false | && |
age >= 18 && age < 65 |
OR: false if both sides are false, otherwise true | || |
month == "April" || month == "June" || month == "September" || month == "November" |
NOT: the opposite of the current value. true becomes false, false becomes true. | ! |
!(a == b) // same as a != b |
Sometimes, we want not just one value but a whole list of values. But we don't want to name them all differently! In this case, we use an array. An array is just like any other type, but instead of a single value we get as many values as we want. All the values must be of the same type.
We can declare a variable to have an array type by typing [ ]
after the type. It then becomes an array of values of that type. For example, int[ ] x;
declares a variable x
which is an array of int
values.
If you imagine a variable as a box holding a value, then int x = 5;
would be a box that contains the value 5
:
5
If we declare a new variable int[ ] arr = [1, 2, 3, 4, 5]
, this declares an array called arr
containing 5 boxes, with each one continaing a value from the list. Note the initialization syntax for arrays!
1
2
3
4
5
We can access and change the whole array by using the identifier arr
. We can access and change individual values in the array by indexing the array. You index an array using the square brackets, with an index inside the brackets.
A word of caution -- the first index of arrays is always 0
! This means that if we wanted to change the 3
value in the array to 100
, we would change index 2
:
arr[2] = 100; // assign the *third* index to 100
1
2
100
4
5
We can add more values to the end of the list by using the append operation: ~=
. If we wanted to add the value 6
to the array, we use the statement arr ~= 6;
The array now looks like:
1
2
100
4
5
6
If we want to do something over and over again, we can use a loop. A loop means that you run a set of code over and over until a stopping condition is reached. The simplest form of loop is called a while
loop. It works very similar to an if
statement, except that it keeps executing the condition check every time before running the loop code.
int x = 0;
while (x < 100) { // this is checked before every loop
writeln("x is ", x);
x = x + 10; // make sure to change x to the next value!
}
The above code will print multiples of 10, starting with 0, and ending with 90. Why not 100? Because 100 is not less than 100! If we also wanted to print 100, we would change the condition to x <= 100
.
What happens when you forget to change the value of x
? The answer is that the while
condition will always be true and therefore will never finish! When this happens, your program will not terminate, and will run forever. This is called an infinite loop. If you need to stop your program, you can use the key-sequence Control-C to stop it.
If we have an array of data, and we want to loop over all the values in the list, D has a convenient feature for this called a foreach
loop. With a foreach
loop, you don't have to worry about properly stopping the loop, this is already done for you. You just need to write the code that has to happen for each value in the array.
The best way to show the syntax of foreach
is with an example. In this example, we are going to print each value from an array using writeln
. Inside the loop, we declare that we want the variable x
to contain the value inside the loop:
foreach(x; arr) {
writeln(x);
}
You can see the syntax inside the parentheses is the name of the variable to use, followed by a semicolon, and then the name of the array to loop over. This kind of loop is one of the most common loops in D for processing data in an array, you will be using it a lot.
For this excercise, we are going to do some math, and figure out the answer. In math, the factorial of a number N is the product (multiplication) of all the numbers from N to 1. So the factorial of 5 is 1 × 2 × 3 × 4 × 5.
Let's calculate the factorial for 12. To do this, we will take a variable x
and count it up to 12. In each loop, you should change x
to the next value, and multiply the variable factorial
by x
. At the end, we will print out the answer of the factorial for 12.
import std.stdio;
void main()
{
int factorial = 1;
int x = 1;
while( ) { // write the condition here
// change factorial and x here
}
writeln(factorial);
}
import std.stdio;
void main()
{
int factorial = 1;
int x = 1;
while(x <= 12) { // write the condition here
// change factorial and x here
factorial = factorial * x;
x = x + 1;
}
writeln(factorial);
}
Try working it out for yourself in VSCode, or on run.dlang.io. If you can't figure it out, you can
Return to home©2023 Steven Schveighoffer