Definition of Functional programming

with examples in Python

What FP is not

There is a popular belief that functional programming in Python (and similarly everywhere else) is just:

In reality, those are just a minor secondary parts of FP.

Core of FP

FP in it’s core is the following.

1️⃣

  1. Pure functions.
  2. Avoiding (or managing) side-effects.
  3. Stateless functions and state management.
details

Definition of pure function is that for a given input, pure function ALWAYS produces the same output.

Example of pure function: f(x) = 3*x

Example of impure function: f(x) = random(1, 10)

Pure functions (as follows from their definition) do not produce side-effects and they are also state-less. To manage state and side-effects some tricky patterns are used (the most famous one being monad).

2️⃣

Functions as 1st class citizens

details

1st class citizenship usually means that FP language implements following things:

  • higher-order functions — functions can be passed as args to other functions (similar to variables)
  • currying and partial application
  • techniques for function composition (threading, piping, again currying and partial application, etc.)

Python supports higher-order function out-of-the-box, and currying together with partial application is supported via functools library.

More sofisticated techniques (like piping) are available through 3rd-party functional libs (like «returns»).

3️⃣

Immutable data structures

Functions always produce new variables (even if they have the same name). Existing variables cannot be modified.

details

FP languages use specially designed data structures, that store immutable structures efficiently. For example, given very large array (of million elements), if you modify just one value — you can create new variable that links to all previous elements, and just adds one more link to new element. Since original variable is immutable too, new variable will too be always immutable.

Python example: tuples data structure is immutable.

4️⃣

APL features

APL is a language from 1960s, which central datattype is multidimensional array. APL syntax rotates around quick manipulations of such arrays without directly using «for» (and similar) loops.

details

Example of APL syntax:

1
2
3
4
⎕IO  0
]box on -s=min
]rows on
assert{'assertion failure'  0⍵:⍺ ⎕signal 8  shy0}

(source: https://xpqz.github.io/learnapl/aplway.html)

APL features are just predefined operations (functions) on arrays and other structures.

This is where python’s map, reduce, filter and list comprehensions really belong.

Important parts of FP

Patterns given below are very common in FP, but they are not as fundamental as core patterns, described earlier.

1️⃣

Lazy evaluation

Calculations are performed as late as possible. It contrasts with imperative approach (eager evaluation).

details

In general it is common in FP first to build transformation (smth like nested functions calls), and apply this transformation only when needed.

It’s worth underlining that it is not merely a programming style (to call functions as late as possible), it is overall language behaviour.

Generators is example of lazy evaluation in Python.

2️⃣

Pattern matching

details

In FP languages it is common to have pattern matching already at arguments level. So, it is possible to define (not just call!) function like: f([x, 0]) = ... ; (f[0, y]) = ...

There just two ways you can call list [x, y] as argument of function in Python: f(x, y) = ... or f(lst) = .... Since 3.10 you can pattern match inside body of the function, still it is not what is meant by «real» pattern matching.

3️⃣

Anonymous functions

details

Anonymous function is usually just a some kind of syntactic sugar, that reduces boilerplate for creating one-shot functions.

It is common in FP languages to rely on them for readability of the code, for functions composition, etc.

Python lambda is anonymous function

4️⃣

Static typing

  1. FP languages are not necessarily statically typed, however when they are, they also have very sophisticated typing system, that supports things like monads, higher-kinded types, etc.
  2. The most distinguished types in FP are Algebraic Data Types that champion approach make illegal state unrepresentable».

See: Functional Programming Patterns

5️⃣

Recursion

Since FP avoids explicit usage of «for» loops, recursion is a common method to traverse nested structures.