nessa-language 0.9.1

An extensible programming language with a strong type system
Documentation
Let's now take a look at the syntax and semantics for defining new functions in Nessa.

## Syntax


You can define and use a function using the following syntax:

```
// Definition
fn funtion_name_1(param_1: Type_1, param_2: Type_2, ...) -> Return_type {

    [...]

    return some_expression;
}

// Usage
let variable: Return_type = funtion_name_1(something_1, something_2);
```

Of course, you can have as many `return` statements as you want (or none at all if your function does not return anything), but 
this is a simple example. Now let's modify this code to create a generic function:

```
// Definition
fn<T, G> funtion_name_2(param_1: Type_1, param_2: Type_2, ...) -> Return_type {

    [...]

    let variable_1: 'T = something;
    let variable_2: Array<'G> = something;

    [...]

    return some_expression;
}

// Explicit usage
let variable_1: Return_type = funtion_name_2<Type_3, Type_4>(something_1, something_2);

// Type parameter inference (when unambiguous)
let variable_2: Return_type = funtion_name_2(something_1, something_2);
```

Here you can see that putting `<T, G>` after the `fn` keyword in the definition **defines** the templates `T` and `G` inside the function body.
They **cannot** be used outside the function body.

> ***Note:*** the `<T, G>` syntax might change to `<'T, 'G>` in a future release for ease of highlighting and uniformization.

## Examples


Let's create some common examples to see how functions work in this language. First off, let's create two factorial functions, a recursive and an iterative one:

```
fn factorial_recursive(n: Int) -> Int {
    if n == 1 {
        return 1;
    }

    return n * factorial_recursive(n - 1);
}

fn factorial_iterative(n: Int) -> Int {
    let res = 1;

    while n > 1 {
        res = res * n;
        n = n - 1;
    }

    return res.deref();
}
```

Now let's dive into generics and make a function that counts how many elements in an array are equal to one given as a parameter:

```
fn<T> count(array: &Array<'T>, elem: &'T) -> Int {
    let res = 0;

    for i in array {
        if i == elem {
            res = res + 1;
        }
    }

    return res.deref();
}
```