If you are a computer scientist you will soon or later be confronted with concepts like pure functions or closures. In most cases you won’t even bother and just use those concepts without thinking much about it. With this post I will give you a short explanation what those terms mean and the concept behind them.

## Pure functions

Pure functions are the easiest to understand. A function is called pure if it has no internal state. This means for a given set of inputs it will always produce the same output without any side effects.

def add(a: int, b: int) -> int: return a + b

Here the `add`

function takes two arguments a and b and returns the sum of both. The function itself doesn’t read or write any internal values. Pure functions don’t need to be methods inside a class and shouldn’t be. In languages like java, where everything needs to be an object, such functions can be marked as `static`

for example.

## First-class functions

Calling a function directly can be nice and all, but in some cases it can become handy if a function could be called dynamically or dependent of the current state of execution. First-class functions can be parameters of other functions or stored in variables. This makes them the backbone of every functional language.

def add(a: int, b: int) -> int: return a + b myFunc: add myResult = myFunc(1, 2)

The add function is assigned to the variable `myFunc`

. Instead of calling `add`

directly `myFunc`

is treated as a function and called with the arguments 1 and 2. The variable `myResult`

will contain the result of the addition 3. With first-class functions it is possible to store functions like other values in complex data structures or pass them deep down to other processes.

An easy example to understand be benefits would be two different operations executed on a list.

def sum(lst: [int]) -> int: if len(lst) == 0: return 0 result = lst[0] for i in range(1, len(lst)): result += lst[i] return result def product(lst: [int]) -> int: if len(lst) == 0: return 0 result = lst[0] for i in range(1, len(lst)): result *= lst[i] return result myList = [1, 2, 3] mySum = sum(myList) myProduct = product(myList)

We have two pure functions. `sum`

adds every element of the list to the result and returns it. `product`

also takes every element but multiplies it with the result. Both functions look nearly the same, just the operation differs. This can be written much cleaner with first-class functions.

def add(a: int, b: int) -> int: return a + b def mul(a: int, b: int) -> int: return a * b def foreach(lst: [int], op: Callable[[int, int], int]) -> int: if len(lst) <= 0: return 0 result = lst[0] for i in range(1, len(lst)): result = op(result, lst[i]) return result myList = [1, 2, 3] mySum = foreach(myList, add) myProduct = foreach(myList, mul)

At first glance this doesn’t safe much code, but we got rid of the code duplication. We have a clean separation between the array traversal and the operations. Even more important: if we want to add another operation like the division we just need to add 2 more lines of code.

## Higher order functions

Higher order functions are functions that can deal with other functions, either as input arguments or as return values. In our previous example the `foreach `

is a higher order function because the parameter `op`

is expected to be a function.

## Closures

Closures are functions that are aware of the scope they where declared in. If they are declared within a function for example they can utilize all of the variables and parameters of this function.

def add(a: int, b: int) -> int: return a+b def add_constant(const: int) -> Callable[[int], int]: def closure(x: int): return add(x, const) return closure addFive = add_constant(5) ten = addFive(5) eleven = addFive(6)

In this example we are using all of our concepts combined. First we have the `add`

function which is pure and does nothing more than add two parameters. There is also the `add_constant`

function which creates another function that will add a constant to any number. Because its return value is another function `add_constant`

is a higher order function. `addFive`

is the result of add_constant with the parameter 5 and for this reason a first class function.

Within `add_constant`

we can find our `closure`

. It will use the outer context of `add_constant`

when called and adds its argument to the variable `const`

which is declared in `add_constant`

. Because `addFive`

was created with `const`

being 5, everytime `addFive`

is called, 5 will be added to the input parameter.