All Erlang Related Articles
Computing Is About Behaving, Not Calculating
The main problem with functional programming is that it was created by mathematicians for mathematicians. In the minds of mathematicians, computation is synonymous with function evaluation. They see the computer strictly as a glorified calculator, a machine for the evaluation of math problems. My position, by contrast, is that computing is not about function evaluation at all but about behavior. In other words, a computer is a behaving machine. Let me explain the difference.
Hidden Variables and Side Effects
Functional programming proponents love to talk about how their style of programming avoids states and state changes. What they fail to tell you is that functions are high-level constructs and that the compiler creates, initializes and manipulates hidden states internally on your behalf. For example, here’s a C function that calculates the sum of integers from 1 to 10:
sum = 0;And here is how it’s done in Haskell:
for (i=1; i<=10; ++i)
sum += i;
Now, the Haskell fanatics will tell you that there was no variable updates in the sum function. Don’t you believe it! There is no way the compiler can add a list of integers without updating at least one variable. The language simply hides it. You may say, so what? As long as the programmer does not have to deal with variables, it prevents side effects, right? Wrong. The worst side effects in programming have to do with timing and unless you can precisely control how and when those variables are changed, you cannot control timing.
Temporal Side Effects
Let’s say you encapsulate a simple sum function in an Erlang process. You can then invoke the process by sending it a message. Subsequently, the process will send another message with the result back to the original sender. Never mind, for now, that Erlang stupidly requires the entire list of integers to be copied onto a message queue and that the receiving process creates a new variable, which is copied onto another queue to be returned to the sender (what an unnecessary waste of CPU cycles!). The point I am getting at is that the time between sending and receiving in an Erlang (or any functional language) program is non-deterministic!
On the Crucial Importance of Temporal Determinacy
This, ladies and gentlemen, is the biggest problem with functional languages: they are temporally non-deterministic. Why is this so important? Well, let’s take security as a case in point. It is entirely possible that some malware surreptitiously replaces your little Erlang process with a spying module. The sending process or client has no way of knowing this. The best and most effective way to detect malware is to use a temporally deterministic system. Such a system is necessarily based on fine-grain concurrency and has a stable temporal signature. What this means is that a number of timing watchdogs can be inserted at various places in the system to detect changes in its temporal signature. Any code modification (such as the insertion of a spying module) would change the signature and trigger an alarm (see Impregnable Security in Concurrent Reactive Systems). Granted, not every part of a software system can be deterministic but every reaction or even chain reaction is.
Security is one thing. Overall reliability and maintainability is another. It is true that a lot of math problems are not concerned with the precise order of most operations but a huge number of real world applications (e.g., simulations, automation, neural networks, etc…) certainly are and the ability to automatically detect changes in event timing at the elementary operation level is crucial to maintainability.
Faking Purity and the Mark of the Beast
The idea that one can implement real world software systems using a purely functional style of programming is fantasy at best, and an outright lie at worst. Let us take the example of a robot that uses two I/O registers to control the movement of a specific actuator. Let’s say that one register is used to start the motion of the actuator and the other to stop it. You can repeat until you turn blue that those registers are not variables but they are. You can scream “MONADS” at the top of your lungs until you drop. Makes no difference, they are still variables. Jumping up and down and foaming at the mouth is not going to help either. :-D
Faking purity and adherence to a mathematical ideal while using impure loopholes to mask the inadequacy of a paradigm is the ultimate exercise in self-deception. Those two control registers are variables that may be used by various behavior subsystems or modules within the robot’s brain. Worst, they may be accessible by any number of cells within a given module. There is only one way to properly manipulate them without introducing all sorts of signal racing and conflict problems and that is to use a temporally deterministic system. Forget threads and all the evil :-) thread monkeys (at Intel, AMD, Sun, IBM, Tilera, Freescale, etc…) who promote them for their crappy multithreaded CPUs. Threads are the absolute work of the devil. Why? Because they are non-deterministic, that’s why. There is a better way to build concurrent deterministic systems without threads. We will need non-threaded, fine-grain, auto-scalable, MIMD multicore CPUs. Unfortunately for those of us who refuse to accept the mark of the Beast (the Algorithm), unless you have the mark on your forehead, you can neither buy nor sell in this business. But that will change soon enough. Slowly but surely, the number of rebels is growing and, sooner or later, the time for the uprising will come. Ahahaha…
Fine-Grain Parallelism, Deterministic Timing and Behavior
I wrote above that computing is about behavior. What I mean is that every elementary operation in a software system (additions, subtractions, divisions, multiplications, comparisons, etc…) should be seen as a basic behaving entity that acts on or reacts to an environmental variable. A behaving entity can be either a sensor (comparator) or an effector (operator). A computer should be viewed as a universal behaving machine (UBM), one which consists of a number of concurrent behaving and communicating entities. The only way to build a truly deterministic system is by adopting a convention whereby every behaving entity executes itself in one system cycle immediately upon receiving a signal. This is called synchronous reactive computing (not the same thing as synchronous messaging). A UBM is a radically different type of computer with a new kind of CPU and programming model. The goal of Project COSA is to pave the way for the development of the first UBM and the first true non-algorithmic, concurrent, synchronous, reactive OS. Until that happens, I will continue to bash existing systems and paradigms and gain new converts, one at a time. It’s not easy but, at least, it’s fun. :-D
How to Solve the Parallel Programming Crisis
Next: Why Functional Programming Is Worse Than Crap: State Changes Are Essential to Reliability