# Functions

Functions and higher-order functions are the key building block of a functional programming language.

In Flix, top-level functions are defined with the
`def`

keyword.
For example:

```
def add(x: Int32, y: Int32): Int32 = x + y + 1
```

A definition consists of the function name followed by an argument list, the return type, and the function body. Although Flix supports type inference, top-level function definitions must declare the type of their arguments and their return type.

In Flix, all function arguments and local variables must be used. If a function argument is not used it must be prefixed with an underscore to explicitly mark it as unused.

## First-Class and Higher-Order Functions

A *higher-order function* is a function that takes a
parameter which is itself a function.
For example:

```
def twice(f: Int32 -> Int32, x: Int32): Int32 = f(f(x))
```

Here the `twice`

function takes two arguments, a
function `f`

and an integer `x`

, and applies `f`

to
`x`

two times.

We can pass a lambda expression to the `twice`

function:

```
twice(x -> x + 1, 42)
```

which evaluates to `44`

since `42`

is incremented
twice.

We can also define a higher-order function that requires a function which takes two arguments:

```
def twice(f: (Int32, Int32) -> Int32, x: Int32): Int32 =
f(f(x, x), f(x, x))
```

which can be called as follows:

```
twice((x, y) -> x + y, 42)
```

We can call a higher-order function with a top-level function as follows:

```
def inc(x: Int32): Int32 = x + 1
def twice(f: Int32 -> Int32, x: Int32): Int32 = f(f(x))
twice(inc, 42)
```

## Function Type Syntax

Depending on the number of arguments to a function, the syntax for the function type differs:

```
Unit -> Int32 // For nullary functions
Int32 -> Int32 // For unary functions
(Int32, Int32, ...) -> Int32 // For the rest
```

## Function Composition

Flix supports several operators for function composition and pipelining:

```
let f = x -> x + 1;
let g = x -> x * 2;
let h = f >> g; // equivalent to x -> g(f(x))
```

Here `>>`

is forward function composition.

We can also write function applications using the pipeline operator:

```
List.range(1, 100) |>
List.filter(x -> x `Int32.mod` 2 == 0) |>
List.map(x -> x * x) |>
println;
```

Here `x |> f`

is equivalent to the function
application `f(x)`

.

## Curried by Default

Functions are curried by default. A curried function can be called with fewer arguments than it declares returning a new function that takes the remainder of the arguments. For example:

```
def sum(x: Int32, y: Int32): Int32 = x + y
def main(): Unit \ IO =
let inc = sum(1);
inc(42) |> println
```

Here the `sum`

function takes two arguments, `x`

and
`y`

, but it is only called with one argument inside
`main`

.
This call returns a new function which is
similar to `sum`

, except that in this function `x`

is always bound to `1`

.
Hence when `inc`

is called with `42`

it returns `43`

.

Currying is useful in many programming patterns.
For example, consider the `List.map`

function.
This function takes two arguments, a function of
type `a -> b`

and a list of type `List[a]`

, and
returns a `List[b]`

obtained by applying the
function to every element of the list.
Now, if we combine currying with the pipeline
operator `|>`

we are able to write:

```
def main(): Unit \ IO =
List.range(1, 100) |>
List.map(x -> x + 1) |>
println
```

Here the call to `List.map`

passes the function
`x -> x + 1`

which *returns* a new function that
expects a list argument.
This list argument is then supplied by the pipeline
operator `|>`

which, in this case, expects a list
and a function that takes a list.

## Pipelines

Flix supports the pipeline operator `|>`

which is
simply a prefix version of function application (i.e.
the argument appears before the function).

The pipeline operator can often be used to make functional code more readable. For example:

```
let l = 1 :: 2 :: 3 :: Nil;
l |>
List.map(x -> x * 2) |>
List.filter(x -> x < 4) |>
List.count(x -> x > 1)
```

Here is another example:

```
"Hello World" |> String.toUpperCase |> println
```

## Operators

Flix has a number of built-in unary and infix operators. In addition Flix supports infix function application by enclosing the function name in backticks. For example:

```
123 `sum` 456
```

is equivalent to the normal function call:

```
sum(123, 456)
```

In addition, a function named with an operator name (some combination of `+`

, `-`

, `*`

, `<`

, `>`

, `=`

, `!`

, `&`

, `|`

, `^`

, and `$`

) can also be used infix. For example:

```
def <*>(x: Int32, y: Int32): Int32 = ???
```

can be used as follows:

```
1 <*> 2
```

## Pure, Impure, and Effect Polymorphic Functions

In Flix every function is pure, impure, or effect polymorphic.

The Flix type and effect system ensures that a pure function always returns the same result when given the same arguments and that it cannot have (observable) side effects.

In Flix every function definition is *implicitly*
marked as `Pure`

.
For example, the function definition:

```
def add(x: Int32, y: Int32): Int32 = x + y
```

is actually equivalent to:

```
def add(x: Int32, y: Int32): Int32 \ {} = x + y
```

Note the annotation for `Pure`

is `\ {}`

.

A function that prints to the console is `Impure`

and must be marked with `\ IO`

:

```
def addAndPrint(x: Int32, y: Int32): Int32 \ IO =
let r = x + y;
println(r);
r
```

since the type signature of the library function
`println`

specifies that it is `Impure`

.

The purity (or impurity) of a higher-order function
may depend on the purity of its argument(s).
For example, whether `List.map`

is pure or impure
depends on whether function we map is pure or
impure.
Fortunately Flix can model such behavior using
*effect polymorphism*.
For example:

```
def map(f: a -> b \ ef, l: List[a]): List[b] \ ef = ???
```

Here the signature of `map`

captures that if the
function argument `f`

has type `a -> b`

with effect
`ef`

then the effect of `map`

itself is `ef`

.
This means that if `map`

is called with a pure
(resp. impure) function argument then the overall
expression is pure (resp. impure).
For example:

```
List.map(x -> x + 123, l) // pure
List.map(x -> println(x), l) // impure
```

Design NoteThe Flix standard library enforces several program invariants using purity. For example, in Flix, the

`Eq`

and`Order`

traits require that their operations are pure. This ensures that collections, such as lists, sets, and maps, do not leak internal implementation details.