Continuous thinking: Essay: TL;DR - functional programming = SQL SELECT statement
Introduction
I am currently in the process of studying F# - a functional programming language -. Since I am a big fan of meta-cognition, I am trying to find out how the mindset of the functional programming paradigm differs from that of a C# one (i.e. the more conventional, object oriented paradigm).
This essay also tries to point out some existing bridges to the functional paradigm that are currently implemented in the imperative programming language C#.
What is "Functional programming" exactly ?
I will reference wikipedia - while it still exists - for the definitions:
In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state.
Let us start with the first bit:
A programming paradigm ? What is that ?
Again from wikipedia:
A programming paradigm is a fundamental style of computer programming. (Compare with a methodology, which is a style of solving specific software engineering problems.) Paradigms differ in the concepts and abstractions used to represent the elements of a program (such as objects, functions, variables, constraints, etc.) and the steps that compose a computation (assignment, evaluation, continuations, data flows, etc.).
I will describe my evolution as a developer by looking at the program paradigms I have used. (An overview of the known paradigms can be found here)
The imperative paradigm
This paradigm describes step by step the procedure that should be followed to solve a problem; you could consider this a long list with instructions: first do this, then do that. These are considered the first 3 language generations. This was the first paradigm I learned writing software.
The imperative paradigm - Generation 1 - Machine code
Back in the days, this meant pulling/plugging wires/switches to develop an app; currently you could compare this to writing your app in a hex editor
As I do not know these hex codes by heart (I used to be able to interpret some of the hex codes during my demo/hacking days way back), I used the code from the next generation to generate this output (Yes, I cheated!).
The imperative paradigm - Generation 2 - Assembly language
The machine hardware is abstracted using mnemonics,f.e. MOV EAX,1; please note that the labels could be considered a part of generation 3. Here is an x86 example:
On a side note: it has been about 25 years ago since I wrote my last applications in assembly, so it took me some time to get this started again. I built the COM-file in FASM (an assembly IDE and compiler) and used dosbox to run it, since a COM-file is considered 16-bit and is unsupported on Windows 7.
The imperative/structured/procedural paradigm - Generation 3 - Procedural language or high-level language
This is the first generation that allows you to represent your problem in the language of your problem domain introducing the concept of variable names/function names etc.. The structured means it tries to avoid GOTO statements, but replaces them with while/Foreach/... Here is a Pascal example:
This also took me a while to write it, since it has been even longer since I wrote (Turbo) Pascal; I used Dev Pascal to write and test this code.
The imperative/structured object-oriented paradigm
While the procedural paradigm offers some abstraction regarding your problem domain, it still requires you to describe your problem domain in a series of procedures. OO design is the next step; OO allows you to group procedures and functions and attach them to their respective data. This allows you to group functionality and data by behavior. Please note that showing this example case in OO is a bit ridiculous, as the functionality is quite simple. However, as complexity grows, OO offers some real advantages.
As this is the language/paradigm I have been working in for the last years, this did not take to much effort...
OO is currently considered as one of the mainstream ways to approach software development (n=1).
The functional paradigm
Ok, we considered my evolution as a developer (and I assume there are a lot of you who have made a similar progression), so now it is time to take a look again at the rest of the definition:
In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state.
Hmmz, what does this mean exactly ? This means that instead of modifying the data, we only have immutable state that we transform through functions. How does this look ? Here is the F# example:
Disclaimer: As I am new to F#, I gave it my best shot, and it took me some time to write.
Luckily I got a confirmation from @Rickasaurus/Richard Meinerich that it is an acceptable implementation.
Hmmz; these look similar; what did I do wrong ?
In hindsight, I would have to say that I probably have chosen a wrong example as this does not demonstrate the advantages of functional programming. So, while this was a nice exercise and fun to do - x86 asm FTW! - , it does not really help a lot.
However, I did read a nice description somewhere on the internet (I can not exactly recall where), but it said something similar to this:
Draw a grid, with the column headers being the Types in your problem, and the row headers the functionalities. When doing OO, you use the columns as building blocks; when doing functional programs, you use the rows as building blocks
This sums it up pretty nicely I think, and it somehow helped me to get started with functional programming. The focus is on the behavior, not on the data structures.
Here's a fact; you are probably using the functional approach already
Yes ? What ? How ?
Ever heard about SQL SELECT statements? This could be considered an application of functional programming, You have an immutable state (within the scope of a query), and map/reduce it at runtime to a new set of data. Or how about Linq ?
In fact, every time you pass in an Action/Func/Predicate in C#, you are actually doing functional programming...
One can do imperative programming in a functional language, as wel as functional programming in an imperative language, but the specific language facilitates the paradigm you should use it for. For example, take a look at that F# code again; do you see a single reference to a specific type in this code ? No you do not. Does this mean that this is dynamically typed then ? No, it is not, as the compiler can figure out the types by analyzing the program.
Conclusion
I wrote this article to enable a paradigm shift, and it worked for me. Functional programming requires a whole new approach to solutions, by representing them in another way. While learning something new, I always consider it a good thing to take a step back, and look at it from a distance. This article was such an attempt, and I hope it was as usefull to you as it was to me.