Warning: this is mainly an unfinished idea, something I haven’t quite well grasped yet. However, I have a Strong Feeling® in my guts that there’s something out there. I mean, there has to be, considering there’s all the more stir around such languages as Ocaml, Haskell and Erlang. And even Lisp is not dead yet, even though the idea is more than 40 years old now.

I’m of course ranting about functional languages, hence referred to as ‘FP’ (I haven’t entered the rant mode yet, but I will, please stay with me).

Ok. What follows is an unstructured, incoherent rambling about miscellaneous observations related to FP.

My main point ..one of them, at least, is that imperative programming, not per se, but as it is usually done, is not really programming, but it is rather something like moving wads of bytes from here to there, mangling a bit over there eventually coming up with the satisfactory result and/or state, and potentially returning something.

The usual construction blocks in imperative programs are expressions and statements. But they are not independent, and do not surve any purpose alone; they are useful only in some very specific context, and to decipher the meaning of the code you have memorize loads of variables such as loop iterators, temporary variables, results of several assignments and worst of all, maybe remember all sorts of intended side-effects introduced by the methods used; often you have to emulate some sort of state machine to get the idea of how some code works. To make this less abstract, consider the following Java snippet implementing quicksort:

    public static void quicksort(double[] a, int left, int right) {
        if (right <= left) return;
        int i = partition(a, left, right);
        quicksort(a, left, i-1);
        quicksort(a, i+1, right);
    }

    private static int partition(double[] a, int left, int right) {
        int i = left - 1;
        int j = right;
        while (true) {
            while (less(a[++i], a[right]));
            while (less(a[right], a[--j])) 
                if (j == left) break;
            if (i >= j) break;
            exchange(a, i, j);
        }
        exchange(a, i, right);
        return i;
    }

It doesn’t even have all the details implemented (less, exchange), but it conveys my idea well (I blatantly copied the code from somewhere; and I think it’s a good implementation for Java environment). For example, take the method partition. It’s task is simple, and you know what it does because you’ve studied all the common sort methods and know their “Big Oh” complexity classes by heart (yes, you, unless you are a weasel and gained a CS degree without studying The CLR book well). But if you didn’t know already how partition works, which is exactly the situation you confront in real life projects: quick - how many minutes it takes for you to understand workings of partition, including edge cases and all execution branches, ie. really understand it? probably way more than necessary. Why? because you cannot understand the whole method just by completely understanding each of the expressions and statements contained.

Now, enter the same quicksort method, this time in Haskell:

quicksort [] = []
quicksort (s:xs) = quicksort [x|x <- xs,x < s] ++ [s] ++ quicksort [x|x <- xs,x >= s] 

And yes, that is the whole implementation. Really!

You could argue that the Java example was contrived (and it was, trust me), but you should still get the point I’m fervently trying to make: functional programming deals with the structure and data flow, encouraging programmers to compute things by mapping a set of values to some other set of values through some particular transformations. And it is the very nature of these transformations that is not well captured by the common imperative-style programs, because it allows programmers to achieve the desired results in 1.7642 gazillions of ways, more than 99% of which are (horribly) bad.

With FP things are a bit different, though. First, it usually prevents the programmer from resorting to Move Wads Of Bytes Here And There -method of “programming”. Erlang does it by discarding the concept of mutable variables. For example, the statement Foo = 42 is not an assignment in a usual sense; it binds Foo to value 42. This is also called single assigment, which means that Foo is eternally bound to the value 42. Saying Foo = 1 afterwards would raise an error.

I guess you, my Gentle Reader, just discarded Erlang from the “languages I should learn” list. Please don’t do it, at least yet.

In concurrent programming, there are several traps for the unwary, like race conditions, locking problems and others, but many of them are due to concurrent data modifications and side-effects, both of which often force programmer to synchronize access to some parts of the code. But these problems are note inherent in all programming paradigms. They are results of using a language and design method intended for sequential, non-parallel data processing. Functional programming languages usually don’t have those restrictions. However, FP-style programming has additional benefits not restricted just to the domain of parallel programming; it is the communication of intent.

Of course, your programming style could be quite different, and perhaps your code is the prime candidate for the book “Beautiful Code: 2nd edition”. But I’m talking about the mere mortals, as myself, here.

So FP focuses on the structure and flow; by avoiding state changes the programmer is coerced to partition problems to smaller subproblems, resulting in cleaner, more coherent result—largely due to the fact that creating a function which returns a list containing two items, a list of employees with salary below given threshold, and initials of the chief executive officer in another item, is a bad code smell that is easy to detect. But such method can be implemented far more subtly using a class with certain side effects, and the public api wouldn’t necessary look that bad (imagine an instance method CompanyInformation#get_info())

My problem is that many of my claims pro FP require more rigorous approach to really prove anything, and I don’t have anything concrete enough to stand my claim. So, I’m sorry, this was yet another half-written thought about a subject I find very intriguing, but lacks more than just polishing to be useful. But I’ll get back on to the subject before the end of this year. Promise.

Leave a Reply