Control Flow - cyxigo/wi GitHub Wiki
Introduction
Control flow is used to decide what blocks of code will execute and how many times.
Statements
Statement is a piece of code that does not produce any side expressions or values. All control flow constructs are statements. Also blocks and variable declarations via := (which we talked about in the very beginning) are statements themselves.
If
The simplest statement: if condition is truthy – execute a block of code; if not – don't.
if (1 < 0) {
std::puts("Won't execute");
}
But we can also provide an else clause. If condition of if is not truthy, the else branch executes:
if (1 < 0) {
std::puts("Won't execute");
} else {
std::puts("This will execute");
}
You can also combine else with if!:
if (1 < 0) {
std::puts("Won't execute");
} else if (1 > 0) {
std::puts("This will execute");
} else {
std::puts("Won't execute");
}
You can create many many branches with this.
While
The simplest looping statement: while condition is truthy, execute the block of code.
i := 0;
while (i < 10) {
std::puts(i);
i = i + 1;
}
This will print:
0
1
2
3
4
5
6
7
8
9
For
The for statement is a looping statement which consists of four parts: an initializer, a condition, an increment, and, of course, the block of code to execute.
Syntax:
for (initializer; condition; increment) {
%% code here
}
For example, our while example can be written as a for statement more gracefully:
for (i := 0; i < 10; i = i + 1) {
std::puts(i);
}
Will print:
0
1
2
3
4
5
6
7
8
9
i := 0;is the initializeri < 10is the conditioni = i + 1is the increment.std::puts(i);is the block of code. A tiny one.
You can use for to go through array elements:
a := [1, 2, 3, 4];
for (i := 0; i < #a; i = i + 1) {
std::puts(a[i]);
}
Will print:
1
2
3
4
Every part of the for is optional, so for (;;) { ... } is an infinite loop.
Break
Sometimes you want to end the loop right from inside the loop itself. That's what break does:
for (i := 0; i < 10; i = i + 1) {
if (i == 4) {
break;
}
std::puts(i);
}
Will print only:
0
1
2
3
Continue
Sometimes you want to skip one iteration of the loop. That's what continue does:
for (i := 0; i < 10; i = i + 1) {
if (i == 4) {
continue;
}
std::puts(i);
}
Will print:
0
1
2
3
5
6
7
8
9
See? It didn't execute std::puts(i); because we decided that if i is 4, we start a new iteration.
Switch
Imagine you have a variable x and you need to check multiple cases of its value, if it's two or three values – if-else branches would suffice, but longer branches of if-else would become harder and harder to read. That's where switch comes in:
switch (x) {
case 0: std::puts("zero");
case 1, 2: std::puts("one or two");
default: std::puts("something else");
}
[!NOTE] Usually, in C-like languages
switchbehaves a bit differently, and requiresbreak– otherwise one case would fall to another one, which is called fallthrough. Wi doesn't have that and does not requirebreakin everyswitchcase.
If x is 0 we print "zero", if it's 1 or 2 we print "one", and by default we print "something else".
switch compares an expression against its cases. Each case represents a case where expression is something, case expects a statement so, of course, you can type something like:
switch (x) {
case 0: {
y := 2;
std::puts("zero, also did you know y is ${y}?");
}
case 1, 2: std::puts("one or two");
default: std::puts("something else");
}
default is what happens if no case matches against compared expression. So it's the default case! It also, must come last, you will catch an error if you try to type something like:
switch (x) {
case 0: {
y := 2;
std::puts("zero, also did you know y is ${y}?");
}
default: std::puts("something else");
case 1, 2: std::puts("one or two");
}
compile error: cannot have another 'case' or 'default' after 'default'
|
7 | case 1, 2: std::puts("one or two");
| ^^^^
--> a.wi:7:5
And from this error you also now know that you cannot have multiple default cases.
You may also have noticed that one case can handle multiple values separated by comma, pretty useful too!
Next: Functions