Functions are the cornerstone of most programming languages. They are the building blocks upon which libraries, API’s and eventually programs are built. The ability to understand how functions enable abstraction and code reuse is one of the first things that are taught to new programmers. Unfortunately, while the use of functions, procedures, and methods are heavily emphasized, functional programming is not. Instead, functions are used interchangeably with methods and procedures in the traditional imperative style. As programming paradigms evolve, neglecting to adapt to these changes can place new students at a disadvantage, making it more difficult for them to learn new standards of coding. Instead, the focus should switch to teaching modern languages that have functional programming built-in.
Functional programming is not new. It has been around at least since the 1950’s when Lisp was first introduced. However, as languages evolved it became more practical and useful to write code in an imperative, procedural style. The trend towards imperative programming was accelerated with the release and monumental success of C, C++, and successors. Most of the languages that are taught in high schools and colleges (Java, C#, Python) are heavily based on the C family.
In an imperative style of programming, the programmer is responsible for describing (in code) both what the code should do, and how it should go about doing it. Of course, programmers don’t write all code from scratch, and the how is often obscured through the abstraction of functions. Don’t want to write your own sorting algorithm? No worries, there’s a Java method for that. However, even though the programmer might not be aware of what the function is doing, he or she is aware that (a) something needs to be done to some kind of data, and (b), a function must be called that will do it. The distinction between the data and the function (code) is clear and complete. We are taught that to solve a given problem, we must first identify the data, then make a decision tree for how that data can be manipulated, and finally, code (or use) functions that will make the changes happen. This works well for a while, but eventually, the data and the functions become too intertwined; creating complex and unmanageable code. So we switch to an object-oriented paradigm where we segment out related data and couple it directly with the functions (now called methods) that work on it. This serves as a tremendous help, but at the core, we are still writing functions that are distinct from data.
Switching from an imperative style of programming to one that is functional is a big change. Bigger in fact then the change from procedural to object-oriented. Functional programming changes the modal for how we program in several ways. First, and most importantly, functional programming removes the separation between data and code. In this paradigm, functions are data; first-class data even. Functions can be assigned to variables, passed as parameters, serialized to files, have computations performed on them, and interact with the language and API in the same way that any other type of data can. This introduces many new complexities but allows for a whole new system for solving problems; it also creates some new ones as well. Some of these problems are solved by another functional programming concept: the idea of pure, immutable functions. Although the full scope of pure functions is outside this post, one major characteristic of a pure function is that it does not alter or depend on any state outside of itself.
To those familiar with Lisp and similar languages, these concepts are nothing new. But to those like myself who learned a C or Java-derived language, they are almost foreign. I’ve known of functional programming for years, but it is only in the last few months that I’ve become comfortable enough with the idea to use it as my goto when solving certain types of problems. Part of my resistance to writing functional code is simple mental laziness. It’s hard to think about functions as data, and even harder to imagine how passing around and combining those functions can be used to solve a problem. It’s much easier to simply write new methods directly, using the tried-and-true method of functional decomposition (which, confusingly, is the near exact opposite of functional programming).
Another block to coding in a functional style is the tools and languages that I routinely use. Although nearly all of the major languages now have support for treating functions as data, and many, such as Java, have great libraries of pre-built pure functions, these features are an add-on and never seem to fully integrate into the language. The core is still object-oriented C procedures, and I don’t think this will ever change.
Thankfully, there is one modern and widely used language that has functions as data built in from the start. It’s a language that we all love to hate but is one that I think should be taught in schools and universities. I’d even go so far as to say that it is the only language that should be taught directly. In addition, the language also has the benefit of being able to run on every device and operating system available. If you haven’t guessed by now, I’m referring to Javascript; specifically JS6 or (ECMAScript 6 for the versioning purists). Everything in Javascript is data: code, objects, files, methods, and functions. But unlike the purely functional languages such as Lisp or Clojure, Javascript still has the syntax and familiar structure of C++ and Java. More importantly, JS6 allows for functional programming to fully mix with the classical inheritance structure of modern OO. Writing object-oriented code in Javascript can be conceptually indistinct from writing the same code in Java or C#.
Javascript has had an adoption path far different from most other programming languages. While there are many valid criticisms against Javascript’s fractured and competing frameworks, almost all of them have embraced functional programming. As coders, we often learn best by seeing what others do, and in no other place is there such a wealth of functional code than in JS-land. Be it streams, maps, promises, or events, almost everything in the JS frameworks make use of functions as data. It is impossible to learn modern Javascript without learning at least some about functional programming.
The functional nature of Javascript along with its rampant popularity has caused some schools to take a closer look. Standford, for instance, had updated all of it’s introductory CS courses to now use Javascript, and even some of their advanced classes require it. More schools need to adapt their CS programs and adopt this approach.
Sources:
Your email address will not be published. Required fields are marked *
2 Comments