Functional programming (FP) is programming with functions. Seems simple! However, function is this case not the same as a traditional function in Java, C++, or most other programming languages. Those functions are more like procedures than true functions. Think back to high school algebra (unless you are in high school, then kudos to you for reading this!). A mathematical function is a device which has a domain (or input) and a desired transformation (or output). The function’s role is to generate the desired output from the input. No external forces bear upon this function; it results in the same output given the same input. This is what computer science considers a pure function. Functional programming is programming with pure functions. It approaches development from a data-first viewpoint.
“Functional programming is programming with pure functions. It approaches development from a data-first viewpoint. “
A functional language describes data structures and how they relate to each other, but it does not make entirely clear the cycles the CPU should execute in order to generate and transform those structures. Thus, the FP language abstracts away the processes of a computer to a higher plane of thought: data. The initial hesitancy that most traditional programmers have in learning FP comes from this source. A computer executes commands. It is imperative. You tell it what to do, and it does exactly, and only that. Machine code is the fundamental basis for representing these commands. However, machine code is almost impossible for a human to reason over, so programming languages were invented, along with their compilers to convert a human-readable syntax into machine language. As machine code is essentially procedural, so too, are the majority of programming languages:
- Variables tell the CPU to put a value in memory and keep a pointer to it.
- While loops and their degraded forms (for & if) tell the CPU to execute certain sequences of commands iteratively until a certain condition is met.
- Functions (non-FP, that is) compartmentalize sequences of instructions to make them easier to reuse.
- Switch statements execute certain code given certain conditions.
Even Object-Oriented (OO) languages (such as Java and C++) use these procedural forms extensively. Thus, OO programming is not a “non-procedural” paradigm, but rather a solution to state management. I believe that many people become interested in programming because they enjoy “making things work.”
“…software has a conundrum. It’s all invented in the minds of people, and its intent is to solve people’s problems.”
These are often the same people that also like mechanics, electronics, mathematics and other related fields. We start programming by telling a computer to do something. Print ‘hello world.’ Run through a while loop to calculate a fibonacci series. Render something on the screen. These are all statements. We are telling the CPU what to do, and it does just that, even when we don’t entirely understand what we are telling it to do (thus the nature of buggy software). This is all fine, except that software has a conundrum. It’s all invented in the minds of people, and its intent is to solve people’s problems. True, computers solve these problems, but the problems never begin as a sequence of commands. The disconnect lies in the fact that a programmer takes these problems and immediately worries about what he will tell the computer to do, without first trying to reason about the nature of the problem. Linus Torvalds, the inventor of Linux said,
“I’m a huge proponent of designing your code around the data, rather than the other way around…I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers [reason] about the code. Good programmers [reason] about data structures and their relationships.”Linus Torvalds, inventor of Linux
Functional Programming allows us to do just what Torvalds stated: reason about data structures and their relationships in an expressive, rather than imperative manner. We express the problem and our desired solution in data. We describe the relationships between data structures in mathematical (pure) functions, and leave the compiler to decide how that will become a series of machine-executable steps. Thus, FP allows us to reason about our data and finally leave the commands to where they belong: on the CPU and not in our heads. It frees us from the 1s and 0s. You may have heard something like this: “Functional programming is a new, hip movement.” Or, perhaps, “It’s new, unproven tech.” What most people do not tell you is that FP is actually older than the OOP paradigm. In fact, LISP, the first FP language, is the second-oldest high-level language, preceded only by Fortran. Long before the days of Java, Python and C++, programmers were writing software in a mathematical format. However, sometime in the late-20th, early-21st century, OOP became the paradigm of choice and has been taught almost exclusively in computer science programs worldwide. Thus, a certain pervasive ignorance toward FP exists, even amongst professional developers. Fortunately, it has gained new popularity in recent years, thanks largely to the growth of the web and its inherent problems, which FP is uniquely positioned to solve. More details on this later.
“It frees us from the 1s and 0s“