In the last post we finished off our dive into functions. In this post we will look at control flow. How do we make a branching decision? How do we loop through something until some condition is met?

I am going to try keep this post short. The reason for this is that although you will invariably need to use control flow expressions in your code, they are stylistically not very functional and there are usually more functional ways to achieve the same thing. We explore those more functional techniques in this and future posts.

## If then else

Other than`match`

(covered later), `if`

is probably the next most useful control flow expression we will touch on in this post. The `if`

expression takes a `bool`

and if `true`

proceeds with the `then`

body. Usually there is an `else`

and we will go through when that is necessary.

```
let b = true
if (b) then printfn "Is true" else printfn "Is false"
```

The above will print out *Is true*, and not print *Is false*.

Maybe we don't want to print out anything if the value is `false`

. We can do this:

```
let b = true
if (b) then printfn "Is true"
```

Now if you changed `let b = false`

, nothing would be printed.

What if we wanted to **return a value** based on some condition though without an `else`

?

```
let v = if(b) then 1 // <- Error: This 'if' expression is missing an 'else' branch.
```

At least the error message is pretty clear about what the problem is. With the print example we were returning `unit`

so it didn't matter if nothing was returned. Here the expression has to return a value because we are assigning that value.

```
let v = if(b) then 1 else 0
```

So depending on whether `b`

is `true`

or `false`

, `v`

will have a value of `1`

or `0`

respectively.

Lets take a look at something a bit more complex:

```
let divideBy d n = n/d
let numerator = 10
let denominator = 2
let j = if(denominator <> 0) then
printfn "Dividing by %i, not 0" denominator
let x = numerator |> divideBy denominator
printfn "The answer is %i" x
x
else
printfn "Dividing by 0"
0
```

Note that we don't have to assign this to a value, here

`j`

but it would be pretty pointless to return a value and not use it. The compiler will give you a warning at this pointThe result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.

This is asking us to call`ignore()`

in each branch of the`if`

expression.

We can have multiple lines in either branch, organized by indentation. Just like functions the last expression is what is returned as the value of the `if-else`

expression for each branch.

### Scope

In the previous post I mentioned scope. This is a good opportunity to demonstrate scope. Check out the assigning of the `denominator`

value below.

```
let divideBy d n = n/d
let numerator = 10
let denominator = 0
if(denominator <> 0) then
printfn "Dividing by %i, not 0" denominator
let x = numerator |> divideBy denominator
printfn "The answer is %i" x
x
else
printfn "Dividing by 0"
let denominator = 1
printfn "Instead by %i, not 0" denominator
let x = numerator |> divideBy denominator
printfn "The answer is %i" x
x
printfn "Denominator is %i" denominator
```

The above prints out the following:

```
Dividing by 0
Instead by 1, not 0
The answer is 10
Denominator is 0
```

Notice here how we set a value for `denominator`

within the `else`

branch that shadows the outside one. Once we are back to the scope outside the if, `denominator`

is back to `0`

, even though it was set to `1`

in the `else`

branch. It was `1`

for the scope of the `else`

branch of the expression as it was set in that scope.

### If / elseif / else

It is (maybe) worth mentioning that you can have more than 2 branches by using `elif`

.

```
if(x = 1) then printfn "x is 1"
elif (x = 2) then printfn "x is 2"
else printfn "x is not 1 or 2"
```

We will briefly cover `match`

next and even when **if / else** seems a cleaner solution, once you are using `elif`

you almost certainly should be using `match`

instead.

## Match

We will hopefully cover pattern matching in more detail in a later entry but no coverage of functional control flow is complete without `match`

.

Lets re-write the previous example using `match`

:

```
match x with
| 1 -> printfn "x is 1"
| 2 -> printfn "x is 2"
| _ -> printfn "x is not 1 or 2"
```

Note that `_`

is a catch-all, like else is.
This is a much cleaner and more functional way to do control flow. A nice benefit here is that the compiler gives you a warning if you are not matching exhaustively on all options of the matched value.

We will hopefully circle around to `match`

again when covering pattern matching as `match`

is far more powerful than demonstrated here.

## for..in

If you need to loop through an entire collection and do something you could use the `for pattern in enumerable-expression do body-expression`

syntax. This is like `foreach`

in many other languages. Lets see what that looks like:

```
let numbers = [1..10]
for x in numbers do
printf "%i " x
```

Output: 1 2 3 4 5 6 7 8 9 10

See how you can easily create a range of values using `start..finish`

syntax. We use this to define `numbers`

. Then for each element of the list we print the value which is in `x`

.

We will hopefully cover collections in an upcoming post but for interest sake lets see how this would be done in a more functional way.

```
let numbers = [1..10]
numbers |> List.iter (printf "%i ")
```

Unsurprisingly the functional approach is to call the `iter`

function on the `List`

module. This `iter`

function has the signature `('T -> unit) -> 'T list -> unit`

. Lets break that down:

`('T -> unit)`

: a function defining the action to take for each element in the list`'T list`

: the list to iterate through`unit`

: returns unit so this function is designed to iterate through a function and do something, not return a value

There are many more functions for working with lists in the `List`

module and matching ones for `Array`

and `Seq`

.

## for..to

While `for..in`

is for iterating over a collection, `for..to`

allows you to iterate from a start value to another. This is like a `for`

loop in other languages.

```
let ns = [|1..10..100|]
for i=0 to ((Array.length ns)/2) do
printf "%i " (Array.get ns i)
```

Output: 1 11 21 31 41 51

In our example we have an array that has numbers 1 to a 100 in increments of 10. We only iterate through half the list.

## while

What if we want to iterate until a certain condition is true? The following code gets a random number until that number is `7`

.

```
let random = new System.Random()
let aNumber() = random.Next(1,10)
let mutable n = 0
while (n <> 7) do
printf "%i " n
n <- aNumber()
```

Output: 0 9 9 1 6 5 2 2 6 6 2 6 6 1 2 3 6 8 8 1 3 2 2

We kept going through the `while`

loop until `aNumber()`

returned `7`

.

## Conclusion

In this post we looked at ways to represent branching logic and ways to iterate over values. Remember that much of this is a very imperative approach and as such is not used a lot in the function paradigm. We looked at some functional techniques for dealing with branching and looping and will continue this in future articles. Next up we look at Pattern Matching.