Functional programming is a *paradigm* - an approach to programming, rather than a rigid set of rules. But there are certain patterns that are often seen in functional programming.

The basic idea of functional programming is to try to decompose a complex problem into simpler problems that can each be solved by a simple function. We can then combine those functions into a more complex function that solve the whole problem.

In functional programming we use *pure functions*. These are just like normal functions, except that they obey a couple of extra rules:

- Pure functions must have no side effects. What does this mean? Typically when you call a function in a procedural language, it might have various effects on the wider system - for example, setting the value of a global variable, or writing data to a file. In functional programming, a pure function is only allowed calculate and return a value, without any other effects.
- Every time you call a pure function with the same input parameters, it must return the same result. This is called
*referential transparency*.

A function in this sense is like a mathematical function. For example, if you calculate the square root of 2, you will always get the same answer. If you calculate the sine of 60 degrees, you will always get the same answer. You wouldn't expect the sine function to return a *different* value depending on whether you had previously called the square root function.

In functional programming, a function can be passed around just like a number, string, list or any other data. You can store a function in a variable, or a list or dictionary. You can pass a function into another function, or even retuirn a function from a function.

A *higher order function* is a function that operates on other functions. For example, the `map`

function takes a function object and a list of values, and applies the function to each element in the list.

Higher order functions and be used to create new functions out of existing functions, for example by concatenating two functions, or but using *partial application*.

Functional programming uses simple pure functions as its building blocks. These functions can often be *mathematically proven* to be correct. This simple means that we can look at all the possible inputs, and demonstrate that the output will be correct in every case. In principle, we could mathematically prove that the entire program is correct (we could prove that it has no bugs), but in practice this is often to complex.

However, since pure functions are self contained, the result of the program doesn't depend on the order in which the functions are evaluated, and it doesn't matter is some functions are evaluated at the same time, on a multi threaded machine. or even on a different machine altogether. The behaviour is predictable and repeatable.

This means that the programs tend not to suffer from difficult to find bugs due to interactions (such as conflicting use of global variables). Multithreading and distributed computing are much easier, making this technique ideal for big data.

With functional programming, since we are working a higher level of abstraction than normal procedural code, the code tends to be shorter. This helps with maintainability and code reuse.

Of course, code sometimes *has* to have side effects. Writing a file to disk is a side effect, but most programs need to write to disk at some point, otherwise how would you save your work? For this reason, functional programming is often used for particular parts of a system, with procedural or OOP used for things like user interface and transferring data via disk or networks.

Copyright (c) Axlesoft Ltd 2021