Functional programming in C

Before explaining how to implement functional programming in C, I will explain shortly what functional programming is.


What is functional programming?

Functional programming is a way of building software by composing pure functions, avoiding shared state, mutable data and side effects.

Pure functions

Pure functions are those functions which always return the same result, for the giving arguments and do not cause side effects.

For example, the following is a pure function:

This function does not have side effects, and if called with same arguments will return always the same result.

Shared state

Any variable, or memory space that is shared, ex: global scope, or any scope accessible by many functions or objects.

Below is an example of changing the shared state by the sum function:

The function sum changes the shared state by changing the value of the variable totalSum.

Mutable data

Mutable data is data that can be changed after its creation, ex: passing by reference an object and changing its properties will also change these properties outside of the functions scope.

On the other hand immutable data are data that cannot be changed after being created, ex: an object that has only “getter” methods, or read only properties.

Side effects

A side effect is an application state change that is observable outside the called function, other than its return value. Examples:

  • Changes in variables outside of the function’s scope
  • Making network requests
  • Doing  I/O operations
  • Logging to screen
  • Calling external processes and changing their state

As described above, functions are first class citizens in functional programming. They can be referred by variables, and can also be passed as arguments to other functions.

Functional programming in C

We can also treat functions as first class citizens in C language, by using function pointers.

Function pointers are variables which hold the memory address of a particular function.

The pointer itself takes 32 or 64 bits of space, depending on the CPU addressing system, which is enough to store the memory address of the function.

After we initialize a function pointer, we can pass it as an argument to another function (or we can also pass directly the address of a particular function as argument too).

Functions that accept other functions as arguments, or return functions as their return types, are known as higher order functions.

Example of using a function pointer and a higher level function:

sumFuncPtr is a function pointer to the sum function. This pointer can be used to call the underlying function like in the first example when, where the result of the call is assigned to the variable sum. This function pointer can also be passed as an argument to higher order functions.

In this example highOrderSumOfThreeAndFour is a high order function because accepts a function pointer as argument.

In my other posts I will write about how to implement Lambdas in C by using gcc macros.