Functional programming is distinguished from its more prevalent object-oriented and procedural cousins by the use of mathematical functions as the central units of abstraction. While object-oriented programs seek to model a problem in terms of a hierarchy of class categories with attached behaviors (a person, a printer, a chat conversation, a network connection manager and all the attendant activities and properties of each) functional programs are focused strictly on the behaviors of those objects.
In that sense, functional programs are a more closely related to their procedural cousins: collections of loose behaviors with no particular affinity for a particular type of object. Unlike its relatives, functional programs have qualities that make them more suitable for high levels of concurrency through process isolation. This simply means we can process more things in parallel with little or no chance of one thing stepping on another thing’s data. Problems that require high levels of concurrency and process isolation are therefore excellent candidates for development in a functional programming language.
Let’s touch on the functional aspects that form the basis of these languages. First and foremost, a mathematical function returns precisely the same output for a given set of inputs. This has subtle implications that are admittedly difficult to convey in a few sentences, but at the heart of this model is the inability to change a value once it has been established. This quality of immutability is responsible for the elimination of side effects: if you cannot change a value during processing you cannot introduce a side effect.
Of course, the whole point of a program is to accept inputs, manipulate that information and produce an output. We still do that in functional languages, but we don’t change the value of inputs; rather, we produce new values when a change is necessary. If we need X squared we don’t square X and save the value back in X; we create a new variable (say X2) to house the change. Functional programs simply won’t let you change a value once it’s been established.
Those with some programming experience will be shocked to discover that you cannot perform something as simple as looping over a set of array values as that requires an index that can be updated on each iteration. Fear not. The same result can be achieved more cleanly and elegantly using recursion, which is beyond the scope of this discussion. Rest assured there’s nothing conventional languages can do that functional programming language can’t.
Akin to the notion of changing a value (not allowed) is that of shared memory or shared variables. Imagine multiple people collaborating on the creation of a sketch where everybody was grasping the pencil and eraser at the same time, pulling it in competing directions all on the same piece of paper. In functional programming, each process has exclusive access to its own pencil and paper; nothing is shared. The composite drawing can then be assembled on a new sheet of paper using the components created by each artist in isolation. Each artist need only send their respective piece in a message attachment for final assembly.
We have only scratched the surface of the qualities of functional programming languages and the attendant benefits, but hopefully you can appreciate the benefit of process isolation and the virtual elimination of side effects: high levels of concurrently running processes reliably communicating through a message service.