What good is functional programming for, anyway?

Useful functional programming concepts that are applicable in many languages

Posted by Sami Tikka on December 15, 2015

I wondered about the need for studying a new paradigm a couple of years ago and asked my colleague the question in the title. Now that I’ve learned a bit about it, I can answer to myself, that it’s good for a lot of things. I’m mostly interested about improvements over the readability and maintainability of the program code, so I’m going to skip concepts bound on language features like type system and focus on things that are very useful with a wide variety of languages.

Wikipedia quote:

“In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions. In functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) each time.”.

Recursion

Let’s consider a common use case found in many programs: A bunch of data is fetched from somewhere, and then we’ll loop over the data in order to append some other data on it or modify/filter it someway. In traditional imperative programming, you might create a function which has an iterative (for-)loop in it, and while looping store the temporary results on some temporary variable(s), which then get modified in each round of the loop.

While storing intermediate stages of computation, these temporary variables have a side-effect of making the program more tedious to follow along just by reading the code, because you have to keep the value of temporary variables in your head along with input/output. Additional complications also arise from the fact, that you have to name those temporary variables in some sensible way. You could of course use names like a1, b2, c10 etc., but this would make the code even more harder to read. Assigning mental meaning for the variables, especially after some time has been passed while you wrote the code, becomes really frustrating when using non-descriptive names.

I’ve found the old saying: naming things is other of the hardest problems in computer science, to be very much true. I like to operate on the program domain when I name things in the code, and usually begin to doubt the validity of my solution for subroutine, when I cannot seem to find a proper name for a variable/function/method/class, that would come naturally from the program domain. Names really matter.

From the functional programming concept of side-effect free functions comes naturally the concept of using recursive functions. A recursive function loops over the data by calling itself, thus having the output of the previous round fed as input for the next round. Recursion avoids the need to use temporary variables by “hiding” the intermediate results in the previous execution round, and makes the code much more elegant and usually easier to reason about. We also avoid the naming problem, by allowing us to operate on things that are clearly subjects/objects/verbs in the program domain. Yay!

Immutability

State is evil, both in code and in server (a DevOps thing). State makes the program logic MUCH harder to follow and reason about. It also requires us to construct complex test logic to make sure the code behaves correctly with all the possible inputs AND program states.

Using immutable data structures forces you to write code, where each modification creates a new copy of the data. Naturally, with each copy comes the problem with storing the data somewhere, and thus, requirement to name the thing somehow. Recursion above helps with this quite a lot, as does the use of collections, described below.

Higher order functions enable great libraries

Higher-order functions are functions that can either take other functions as arguments or return them as results.

I think one of the best day-to-day use case for higher-order functions are collections, ie. data structure which has a few standard methods, like map/filter/reduce etc. They allow very elegant, almost poetic manipulation of data by chaining the collection’s method calls (first method’s output is the input of the second method), which makes the data flow very easy to follow along.

Collections are usually included in functional programming languages’ standard library. Good libraries also exist for almost all languages, and using a good (preferably immutable) collection library is highly recommended in any language.

Applicable: everywhere

These concepts are actually applicable in many reasonably modern languages. Studying functional programming has definitely improved my code and structure of the programs I write.