Tuesday, September 21, 2021

Functional programming requires different discipline

I am worried about the programming industry. Specifically, I fear that we may have trapped ourselves in the object-oriented programming paradigm. I can explain, but it will take some time. Please bear with me.

Paul Graham has written several articles, most of them (if not all of them) thoughtful and thought-provoking. Some of them discuss programming languages. One of them (I cannot find it now) discussed the idea of programming languages and how different languages hold different constructs. If I remember correctly, Graham posited that older programming languages were simpler and modern languages had constructs that were not available in older languages.

If you "stacked" the languages from oldest (on the bottom) to newest (on the top) then programmers could pick their favorite language and look up (at newer languages) and down (at older languages). Graham commented that from such a view, the older languages made sense, because one's favorite language (from which one looked down) contained the things in the older languages. Older languages had constructs that were identical or similar to your language. They didn't have all of the constructs, but the ones that they did have were recognizable.

Conversely (Graham continued), looking up the stack at newer languages was less clear. Those newer languages had constructs and ideas that weren't in your favorite language, and weren't known to you. They looked weird.

I'm not sure I agree completely with this idea. If we start with a simple stack of assembly language, FORTRAN, COBOL, BASIC, Pascal, C, C++, and Java, we can see that yes, later languages have features that are not available in earlier languages. Pascal lets you define records and sets, which are not available in BASIC or FORTRAN. C++ and Java have classes and allow overloading of functions. But the view from new to old is not always clear. BASIC had GOTO, which has all but been removed from modern languages. COBOL had level-88 values, which do not exist in newer languages. FORTRAN-66 had the arithmetic IF statement with its three-way branching, which looks weird from any other language, old or new. The simple rule "old is familiar and newer is strange" doesn't hold.

Instead of programming languages, perhaps it is better to think about programming paradigms. These are broader and not tied to a single language. I can see four major programming paradigms: simple procedural programming, structured programming, object-oriented programming, and functional programming. We developed these paradigms in that sequence, with procedural programming in the 1960s (FORTRAN, COBOL, BASIC), structured programming in the 1970s (Pascal, C), object-oriented programming in the 1990s (C++, Java, C#), and functional programming in the 2000s (Haskell, Erlang). [The lists of languages are not complete, and the years reflect the popularity of the languages, not the initial design.]

My personal history with programming had all of these paradigms. Over time, I moved from one paradigm to another. I started with simple procedural programming (BASIC, FORTRAN) and later moved to structured programming (Pascal, C). That transition was fairly easy. I understood the concepts and had only to learn discipline to apply them.

Later, I moved to object-oriented programming (C++, Java, C#). Changing from structured programming to object-oriented programming was more difficult. That may have been due to age (I was fifteen years older) or perhaps the learning method (I learned structured programming in a classroom; object-oriented programming was on my own). It may be that object-oriented programming is that much harder that structured programming. But learn it I did.

Recently I have looked into functional programming, but only out of curiosity. I'm not using functional programming for any serious projects. (At least not yet.)

Notice that my progress was moving up the stack of programming paradigms. I started with the simplest paradigm (procedural) and moved to structured programming and then to object-oriented programming.

Functional programming is different from the other programming paradigms. Procedural programming is the base, upon which is built structured programming. Object-oriented programming is built on top of structured programming. The three of them make a nice little tower.

But functional programming is not an extension of object-oriented programming. It doesn't include the concepts of OOP (data-hiding and polymorphism). You don't build function-oriented programs out of classes. (I recognize that there are programming languages that combine functional programming and object-oriented programming, but they are hybrids. More on them later.)

Functional programming, in my view, is an alternative to structured programming. It sits by the side of our tower of paradigms, not on top. Just as structured programming imposed discipline on procedural programming, function programming imposes discipline on procedural programming -- but a different set of rules.

To transition from object-oriented programming to functional programming, one has to forget object-oriented programming, and then forget the discipline of structured programming, and then -- and only then -- can one learn the discipline of functional programming. (The hybrid of OOP and FP is another level on top of functional programming, much as OOP is another level on top of structured programming. We're building another tower of programming paradigms, with procedural at the bottom, then functional programming, and then object-oriented/functional programming on top.)

Let's get back to the transition from object-oriented programming to functional programming, by forgetting object-oriented programming and structured programming and building functional programming on top of procedural programming.

That transition is difficult, but not impossible. At least, not for me, because of the sequence in which I learned programming. I started with procedural programming, and then added structured programming and then object-oriented programming. In my brain, I can ignore the later additions and recall pure procedural programming. (I can still write programs in BASIC.)

But that is me. I suspect it holds for programmers who followed that same path.

What about other programmers?

For the past two decades, programmers have been taught object-oriented programming, and nothing else. They were not taught procedural programming, followed by structured programming, followed by object-oriented programming. No indeed. The primary programming languages for learning was C++, later replaced by Java, later replaced by C#, and today Python (and possibly JavaScript).

We have been teaching people how to write object-oriented programs, and nothing else. That's going to make the transition to functional programming extremely difficult. Modern-day programmers, who learned only object-oriented programming, cannot simply forget "the new bits" and revert to the old style or procedural programming.

One cannot simply jump from an object-oriented programming language into a functional programming language. For programmers who know object-oriented programming and nothing else, they cannot "forget the new stuff and learn the new bits" because everything, to them, is connected. Switching to functional programming is a complete reset. They have to forget everything (well, almost everything) and start over.

That's a big task.

I'm not saying that functional programming is wrong, or that we shouldn't use it. Nor am I saying that only the really smart programmers should attempt to move from object-oriented programming to functional programming.

My point is that the transition requires one to unlearn a lot of techniques, techniques that have become habits. The transition is a large change, and will require time, effort, and patience.

No comments: