# 5. Functions

## Defining and calling
```stencil
func add(a, b) {
    return a + b;
}
print(add(2, 3));   // 5
```
A function with no `return` returns `null`.

## Parameters
Parameters are positional. Type annotations are allowed (and ignored):
```stencil
func greet(name: string, times: int) {
    let i = 0;
    while (i < times) {
        print("Hello " + name);
        i = i + 1;
    }
}
greet("Ada", 2);
```

## Recursion
Functions can call themselves:
```stencil
func factorial(n) {
    if (n <= 1) { return 1; }
    return n * factorial(n - 1);
}
print(factorial(5));   // 120

func fib(n) {
    if (n <= 1) { return n; }
    return fib(n - 1) + fib(n - 2);
}
print(fib(10));   // 55
```

## Arrow functions (single expression)
For short, one-expression functions use `=>`:
```stencil
square(x) => x * x;
double(x) => x * 2;
print(square(6), double(6));   // 36 12
```

## Functions are values
You can pass a function to another function (used by the web server in lesson 12):
```stencil
func apply(f, x) {
    return f(x);
}
square(n) => n * n;
print(apply(square, 9));   // 81
```

## Scope
Variables created inside a function are local to it. Use `return` to send a result out.
```stencil
func makeCounterStart() {
    let count = 100;
    return count;
}
print(makeCounterStart());   // 100
```

Next: [Collections](06_collections.md)
