By Stepan Mitkin
Part 1 of 10
Functional programming is gaining popularity nowadays. It is being more and more widely accepted as "mainstream". Why? Because it feels "esoteric" or "mathematical"? Maybe. But apparently, the functional programming style provides certain practical benefits. Here are a few of them:
A better separation of concerns. Function composition and closures are an easy way to draw healthy boundaries within a program. They glue together different algorithms that can be developed and tested separately. They help the programmer keep different ideas about the program apart.
No need to keep track of changing values of variables. In conventional languages, the same variable may hold different values at different moments of time. When looking at any given part of a program, the programmer must deduce the expected value of the variable from the context. And it must be done for all occurences of a variable, because its value can change. Tracking the changes requires significant mental effort. This effort is not needed with functional languages. They guarantee that there is only one immutable value behind each symbol.
Each algorithm has an explicit input and output. Functions take arguments by value. Returning the result of computation is the only way how a function can change the outside world. As a result, a function can be seen as a system that has a clearly defined input and output. This separation of the input and output has an extremely positive effect on ergonomics. All effect of a function invocation is recorded in a very visual way. There is no "something" that get changed "somewhere". Visualizing this "something" is hard work with conventional languages.
In spite of the above, functional programming is still not the primary way of how people write programs. Let us look at some of the reasons for that and find possible ways to mitigate those reasons.
Recursion is not immediately visible. In conventional languages, loops are implemented with special keywords. These keywords are easy to spot. The functional way to do loops is recursion. The problem with recursion is that recursion takes some effort to recognize it in source code. The user must compare the name of the current function to the name of the function being called. It gets even worse with indirect recursion. How to fix that? Let us add a new rule to the programming style: each recursive call must be marked with a special comment "recursion". Of course, a good IDE should detect recursion automatically and highlight it.
Recursion allows for only one loop per algorithm. This is an inherent disadvantage of functional programming. In contrast, algorithms in conventional languages may have several loops. Luckily, many loops can be represented as calls to standard looping functions like filter, map, fold and others.
Tail recursion is a trick. Some recursive algorithms must be implemented with tail recursion. Otherwise they get too slow. But tail recursion is not intuitive. It requires very intensive thinking to do it right and adds complexity to the original algorithm. Tail recursion is an evil remnant of ancient compilers. Hopefully, developments in compiler technology will take care of that.
Non-trivial syntax. This issue is not as easy as it seems. There are a lot of people who think that it is not a problem at all. They find the syntax of popular functional languages convenient. But there are also many people who consider functional languages "cryptic". Let us admit: it is way too easy to make a "write-only" functional program. A program that would be really difficult to read and understand.
The ideas behind functional programming are simple, powerful and practically useful. But the presentation layer is of a very low quality.
It is the visible appearance of functional programs that makes them not attractive.
But isn't the essense more important than the form? Who cares about the wrapping if the gift inside is good?
With information technology, we cannot take the gift and throw out the wrapping. All kinds of information, no matter how abstract, must be represented in a specific form. The choice of form is extremely important because it greatly affects productivity. Productivity in software projects is closely tied to the amount of effort required for understanding. The harder it is to understand a program, the more effort is needed to develop and maintain it.
This is especially relevant to projects that have more than one developer. Any given piece of code gets written once, but is read many times by several people. Whatever makes understanding easier boosts productivity.
In addition, it takes less time to find bugs in a program that is easy to understand. That is why easy understanding also improves quality.
Any non-trivial program consists of 3 parts:
Algorithm is the core of software. It is the algorithm that produces the desired output of a program. Therefore, if the algorithm is easy to understand, the whole program is easy to maintain, extend and document.
Unfortunately, the traditional way of recording algorithms is wrong. This is a major problem of programming in general, not only functional programming. Algorithms in most of the modern programs are written using text. This text is called "the source code".
Usually, source code is indented in a special way and highlighted with different colors in the editor. But it is plain text. Text is bad because humans are not very good at understanding text. Their eyes and brains have been optimized for seeing images during millions of years. Text is a recent invention. The human biological hardware is not natively compatible with text.
If the algorithm is presented as an picture instead of text, it can be easier to understand.
There are a lot of ways to draw an algorithm. Choosing the right one is critically important. A bad picture can be worse than text. A good picture will leverage the ability of the human being to perceive information simultaneously.
Flowcharts are a popular graphical notation for representing algorithms. Many developers do not like flowcharts. The reason is that complex algorithms tend to end up in badly cluttered flowcharts. Those can be harder to figure out than text-based programs. As a result, graphical programming is often dismissed as an unsuccessful experiment.
But the problem is not in graphical programming itself. The problem is that flowcharts as a graphical language are not good enough. The good news is, it is possible to improve this language.
DRAKON provides such improvement. It offers several simple, but effective rules that cardinally increase readability of a diagram. DRAKON is a visual language that can be described as flowcharts optimized for ergonomics. The creators of DRAKON paid great attention to human visual habits. Every little detail of DRAKON is aimed at ensuring fast and easy understanding.
That is why DRAKON is an excellent candidate for visualization of a functional programming language. The clarity of DRAKON is something that functional programming can greatly benefit from.
Let us consider the hybrid language DRAKON-Erlang.
The choice of Erlang is not arbitrary. It is not only an excellent functional programming language. The main advantage of Erlang is that it was designed from the beginning to make concurrent programming easy. And nowadays, all programming is concurrent. Single-core processors become increasingly hard to find. In addition, Erlang makes distributed computing and clustering a breeze.
The combination of a solid functional programming foundation, built-in concurrency and visual clarity make DRAKON-Erlang a very promising technology.