Decisions, decisions

So far everything we've typed in was executed exactly once, but there are far more useful behaviours than that. In this section we'll write programs that make decisions and that repeat steps.

if statements

>>>> if 31*31 < 1000 {
....   print("Less\n")
.... } else {
....   print("More\n")
.... }
Less

This statement contains two print statements, but only the first one is executed, because 31*31 is 961 which is less than 1000. If you change it to 32*32 then the second one will be executed instead.

The word if is a keyword. The expression after it is called the condition. It's a separable part, and we can type it in on its own:

>>>> 31*31 < 1000
true: bool

Note that the type is bool; the condition has to be a boolean expression.

Next comes a block of statements, enclosed in { and }. In general, there can be zero or more statements here. There's exactly one statememt in our example. It's a separable piece, and we can type it in on its own:

>>>> print("Less\n")
Less

Note that the { and } are part of the if statement; you have to omit them when you pull the print statement out. Note also that we indented the print statement when it was inside the if statement; you don't have to do this, but it's helpful for people reading the code. Statements in Welly are sometimes nested quite deeply, and without the indentation it can be difficult to tell what's inside what.

The word else is another keyword. After that comes a second block of statements. You can omit everything from else onwards; if you do, it means the same thing as leaving the second block empty.

Multi-line statements

You probably noticed that the if example runs onto five lines. You can actually write it all on one line if you prefer:

>>>> if 31*31 < 1000 { print("Less\n") } else { print("More\n") }
Less

If you do use the five-line version, nothing happens until you press "Enter" for the fifth time. Before that, Welly just prints .... instead of the usual >>>> to let you know that it's waiting for more input.

If you make a mistake while typing in a long statement, make sure you get the >>>> prompt back before trying again. If you don't, Welly will probably think you're just continuing on from where you got to. A good trick for telling Welly not to wait for more input is to type lots of close bracket characters; that usually gives a harmless error:

>>>> if 31*31 < 1000 {
....
....
.... )))))))))))))
ASTError: Unmatched "{"
at line 13, col 17
if 31*31 < 1000 {
                ^

Read more about newlines.

Comparison with other languages

If you've ever used C-family programming language such as C, C++, C#, Java or Javascript, the if syntax is probably quite familiar. There are three slight differences:

  • Brackets are not needed around the condition. You can put them in if you want, but why?
  • Second, the blocks of statements must be enclosed in { and }, even if there is only one statement inside. Omitting the braces has proved to cause bugs in other languages, so it's forbidden in Welly.
  • Third, you mustn't put a newline before the word else. If you do, Welly has no way of knowing whether you plan on typing else next. In this situation it makes a guess that you're going to omit the else clause.

while statements

>>>> var x = 20;
>>>> while x*x < 1000 {
....   print("Less\n")
....   x += 1
.... } else {
....   print("More\n")
.... }
Less
Less
Less
Less
Less
Less
Less
Less
Less
Less
Less
Less
More
>>>> x
32: int

The syntax of a while statement is the same as that of an if statement apart from the initial keyword. The meaning is the same, except that if the condition is true, after executing the first block of statements Welly repeats the entire whilestatement. The optional else clause is executed when the condition is false.

In this example, the while statement is executed thirteen times: once for each value of x from 20 to 32 inclusive. The first twelve times, the condition is true, so the first block is executed and the loop repeats. The last time, the condition is false so the second block is executed and the loop exits.

The statement x += 1 is an abbreviation for x = x + 1. This is the line which changes the value of x on each iteration, such that the loop eventually terminates.

break and continue

>>>> const n = 2047
>>>> var x = 3
>>>> while x*x < n {
....   if n % x == 0 {
....     print("Composite\n")
....     x
....     break
....   }
....   x += 1
.... } else {
....   print("Prime\n")
.... }
Composite
23: int

The above code tries to find a number that divides exactly into 2047. It finds one: 23.

The control flow is similar to the previous example. x starts at 3, and increases by one on each iteration of the loop. If ever x were to become large enough (46*46 exceeds 2047) the loop would exit and the word "Prime" would be printed. However, x never gets that big, because of the break statement.

When x reaches 23, the condition of the if statement is true (2047 % 23 computes the remainder when 2047 is divided by 23). As usual, you can verify it:

>>>> 2047 % 23
0: int

At that moment, Welly executes the block of statements inside the if statement. It prints the word "Composite". The next line, x, is an expression, so it prints its value and type. Then it executes break, which terminates the loop immediately without executing the else clause.

The continue statement is similar; it modifies the control flow of the enclosing loop. Whereas break causes the entire loop to terminate, continue only causes the current iteration to terminate. Welly executes the next iteration as normal.

>>>> var x = 0
>>>> while x < 20 {
....   x += 1
....   if x % 3 == 0 { print("Fizz\n"); continue }
....   if x % 7 == 0 { print("Buzz\n"); continue }
....   x
.... }
1: int
2: int
Fizz
4: int
5: int
Fizz
Buzz
8: int
Fizz
10: int
11: int
Fizz
13: int
Buzz
Fizz
16: int
17: int
Fizz
19: int
20: int

The above code prints out all numbers up to 20 that are not divisible by 3 or 7. Numbers that are divisible by 3 are replace by "Fizz", and those that are divisible by 7 are replaced by "Buzz".

Note that we've moved the increment operation to the beginning of the loop. If we hadn't, the loop would run for ever. Try it.

Each of the if statements in this example has two statements inside it, written on a single line. We have to separate the statements with a semicolon (;).