In a purely procedural style, data tends to be highly decoupled from the functions that operate on it. Procedural is a type of imperative programming style. An imperative language uses a sequence of statements to determine how to reach a certain goal. These statements are said to change the state of the program as each one is executed in turn.
In an object oriented style, data tends to carry with it a collection of functions.
Functional programming (often abbreviated FP) is the process of building software by composing pure functions, avoiding shared state, mutable data, and side-effects. A function is called ‘pure’ if all its inputs are declared as inputs – none of them are hidden – and likewise all its outputs are declared as outputs. Functional programming is about writing pure functions, about removing hidden inputs and outputs as far as we can, so that as much of our code as possible just describes a relationship between inputs and outputs. Let’s not hide what a piece of code needs, nor what results it will yield. If a piece of code needs something to run correctly, let it say so. If it does something useful, let it declare it as an output. When we do this, our code will be clearer. Complexity will come to the surface, where we can break it down and deal with it.