# Control flow

## Blocks

Every block in Aiken is an expression. All expressions in the block are
executed, and the result of the last expression is returned.

```aiken
let value: Bool = {
    "Hello"
    42 + 12
    False
} // False
```

Expression blocks can be used instead of parenthesis to change the precedence of operations.

```aiken
let celsius = { fahrenheit - 32 } * 5 / 9
```

## Matching

The `when *expr* is` expression is the most common kind of flow control in Aiken code. It
allows us to say "if the data has this shape then do that", which we call
_pattern matching_.

Here we match on an `Int` and return a specific string for the values 0, 1,
and 2. The final pattern `n` matches any other value that did not match any of
the previous patterns.

```aiken
when some_number is {
  0 -> "Zero"
  1 -> "One"
  2 -> "Two"
  n -> "Some other number" // This matches anything
}
```

Aiken's `when *expr* is` is an expression, meaning it returns a value and can be used
anywhere we would use a value. For example, we can name the value of a when
expression with a `let` binding.

```aiken
type Answer {
  Yes
  No
}

let answer = Yes

let description =
  when answer is {
    Yes -> "It's yes!"
    No -> "It's not yes."
  }

description  // => "It's true!"
```

## If-Else

Pattern matching on a `Bool` value is discouraged and `if / else`
expressions should be use instead.

```aiken
let some_bool = True

if some_bool {
  "It's true!"
else {
  "It's not true."
}
```

Note that, while it may look like an imperative instruction: if this then do
that or else do that, it is in fact one single expression. This means, in
particular, that the return types of both branches have to match.

## Destructuring

A `when *expr* is` expression can be used to destructure values that
contain other values, such as tuples and lists.

```aiken
when xs is {
  [] -> "This list is empty"
  [a] -> "This list has 1 element"
  [a, b] -> "This list has 2 elements"
  _other -> "This list has more than 2 elements"
}
```

It's not just the top level data structure that can be pattern matched,
contained values can also be matched. This gives `when` the ability to
concisely express flow control that might be verbose without pattern matching.

```aiken
when xs is {
  [[]] -> "The only element is an empty list"
  [[], ..] -> "The 1st element is an empty list"
  [[4], ..] -> "The 1st element is a list of the number 4"
  other -> "Something else"
}
```

Pattern matching also works in `let` bindings, though patterns that do not
match all instances of that type may result in a runtime error.

```aiken
let [a] = [1]    // a is 1
let [b] = [1, 2] // Runtime error! The pattern has 1 element but the value has 2
```

## Assigning names to sub-patterns

Sometimes when pattern matching we want to assign a name to a value while
specifying its shape at the same time. We can do this using the `as` keyword.

```aiken
when xs is {
  [[_, ..] as inner_list] -> inner_list
  _other -> []
}
```

## Checking equality and ordering in patterns

The `if` keyword can be used to add a guard expression to a when clause. Both
the patterns have to match and the guard has to evaluate to `True` for the
clause to match. The guard expression can check for equality or ordering for
`Int`.

```aiken
when xs is {
  [a, b, c] if a == b && b != c -> "ok"
  _other -> "ko"
}
```

## Alternative clause patterns

Alternative patterns can be given for a when clause using the `|` operator. If
any of the patterns match then the clause matches.

Here the first clause will match if the variable `number` holds 2, 4, 6 or 8.

```aiken
when number is {
  2 | 4 | 6 | 8 -> "This is an even number"
  1 | 3 | 5 | 7 -> "This is an odd number"
  _ -> "I'm not sure"
}
```

If the patterns declare variables then the same variables must be declared in
all patterns, and the variables must have the same type in all the patterns.

```aiken
when list is {
  [1, x] | x -> x // Error! Int != List(Int)
  _ -> 0
}
```

## Todo

Aiken's `todo` keyword is used to indicate that some code is not yet finished.

It can be useful when designing a module, type checking functions and types but
leaving the implementation of the functions until later.

```aiken
fn not_sure_yet() -> Int {
  // The type annotations says this returns an Int, but we don't need
  // to implement it yet.
  todo
}

fn idk() {
  favourite_number() * 2
}
```

When this code is built Aiken will type check and compile the code to ensure it
is valid, and the `todo` will be replaced with code that crashes the program if
that function is run.

A message can be given as a form of documentation. The message will be traced
when the `todo` code is run.

```aiken
fn not_sure_yet() -> Int {
  todo("Believe in the you that believes in yourself!")
}
```

When the compiler finds a `todo` it will print a warning, which can be useful
to avoid accidentally forgetting to remove a `todo`.

The warning also includes the expected type of the expression that needs to
replace the `todo`. This can be a useful way of asking the compiler what type
is needed if you are ever unsure.

```aiken
fn foo() {
  my_complicated_function(
    // What type does this function take again...?
    todo
  )
}
```
