# Control Flow ## simple if expression Simple if expressions produce a value specified in the if body. Since the else part is missing, it is assumed to be a `null`. In REPL, a multiline if statement can be executed by suffixing a back-slash character (`\`) at the end of the line to indicate that the next line is a continuation. ``` let n = 0; let s = if n == 0 { \ "zero" \ }; puts(s); ``` Note: There should not be any space following the `\` character. Alternatively, instead of using the slash suffix, you can also create file via the cat command available in posix systems. ## if-else expression Save the following script in a file. e.g. 'if.p2'. On posix systems, you can use 'cat' with 'EOF' to create this file on your terminal. Alternatively, an editor may also be used. ``` cat > if.p2 < match.p2 <> "); let r = match tolower(s) { "a" | "e" | "i" | "o" | "u" => { "vowel" } "b"..="z" => "consonant", _ => { "others" } }; puts(r); EOF ``` Execute the program as follows: ``` p2sh match.p2 -->> a vowel p2sh match.p2 -->> b consonant p2sh match.p2 -->> ? others ``` ## Loop statements The loop statement executes the loop body infinitely. To break out of the loop, use the break statement. ``` let n = 1; loop { \ if n > 5 { \ break; \ } \ puts(n); \ n = n + 1; \ } ``` Output: ``` 1 2 3 4 5 true ``` Note that the `true` at the end is the value of the last expression evaluated in the loop and can be ignored. In this case it is the result of the if expression. ## While The same code can be written using while ``` let n = 1; while n <= 5 { \ puts(n); \ n = n + 1; \ } ``` Output: ``` 1 2 3 4 5 false ``` ### loop labels break and continue statements can also have labels in them. This is helpful when loops are nested. ``` cat >> while.p2 < loop.p2 <> let add = fn(a, b) { a + b }; >> add(1,2) 3 ``` ### Function statements ``` >> fn f1() { 1; } >> fn f2() { return 2; } >> f1(); 1 >> f2(); 2 ``` ### Closures Closures are functions that can capture the surrounding variables at the time of its definitions. In the following example, the inner anonymous function is a closure that closes over the variable 'value' that is passed as an argument. In this case, the values of that variable are `doughnut` and `bagel`. Note that the inner anonymous function uses the surrounding variable `value`. ``` >> fn make_closure(value) { return fn() { puts(value); } } >> let doughnut = make_closure("doughnut"); >> let bagel = make_closure("bagel"); >> doughnut(); doughnut >> bagel(); bagel ``` A more useful example ``` cat >> filter.p2 <