Coding, maths and art

Functional programming

Functional programming is a programming paradigm where a complex problem is decomposed into simpler problems by breaking it down into separate functions, each solving part of the problem.

This compares with, for example, object oriented programming where a complex problem is decomposed by breaking it down into a set of separate software objects.

The two are not mutually exclusive. Most styles of programming allow (and recommend) breaking complex functions into a set of simpler functions. The term functional programming is usually used when some of the techniques below are used.

Avoiding side effects

With object oriented programming we strive to ensure that the objects we create are encapusulated. This means that the data the object uses is stored within the object and can only be accessed via the object’s methods (data hiding). This has benefits, in particular it avoids unpredictable side effects.

If functional programming, we are also concerned with side effects. The ideal situation is where a particular function, passed the same parameters, will always return the same result. This allows the code to be tested easily. Here is an example (in Python, but it should be understandable to non-Python programmers):

def multiply(a, b):
    return a*b

def cube(x):
    return multiply(x, multiply(x, x))

The first function multiply clearly has no side effects, its output is entirely predictable based on the inputs. The second function cube also has no side effects, because it depends only on the multiply function, and that has no side effects.

This function has side effects:

def store():
    global s
	s += input("Type some text")
	return s

This function invites the user to type in some text, then appends the result to a global variable, and returns the result. The result of this function is totally unpredictable - it depends on what the user types in, and also whatever the global variable s contained before the function was called.

Function references

A common feature of functional programming languages is that they allow you to take references (or pointers) to functions. This means that a function can be stored in a variable, or passed as a parameter to another function. The reference can then be applied later. Here is an example, using the multiply function:

m = multiply

x = m(2, 3)

In Python, a function name such as multiply without brackets acts as a function reference. We assign this the the variable m. Now m also holds a reference to the multiply function, so m(2, 3) is the same as calling multiply(2, 3) and returns a value 6.

Here is another example:

def applytwice(f, v):
    return f(f(v))

x = applytwice(cube, 2)

Here, applytwice takes a function reference f and applies it twice to the value v. That is, it calculates f(v) and then calculates f() of the result. We can call it with the function cube and the value 2, and it will calculate 2 cubed, cubed. In other words, 2 to the power 9, or 512.

But we could use applytwice with any other function. The only requirement is that the function must take a single parameter, because we call f(v).

Other features and patterns

Functional programming languages typically support lambda expressions (anonymous functions).

They also usually allow closures and currying.