A definition of functional programming is very hard to pin down.

Many introductions to functional programming start with map and other higher-order functions, and never really draw the rest of the owl. Since these tools are available even in the most staunchly object-oriented languages, like Ruby, they don’t make for a particularly good definition of functional programming.

The defining component is sometimes simple: parameter order. While I’ve argued before that we should get rid of positional parameters entirely, they’re still an important part of programming today. What’s the difference between f a b and a.f(b) ? It’s really just the order of the parameters. (I would also like to submit [a f:b] for examination 😈)

Some definitions of functional programming are more encompassing. The opening paragraph of this Wikipedia article, for examples, suggests that functional programming primarily has to do with math. Languages that are particularly type-heavy, like ML and Haskell, with their monoids and monads, bear this out.

Others define functional programming primarily in terms of immutability, viewing functions as a means to that end. There are posts describing functional programming that talk about immutability before any other feature of the paradigm, including actually using functions.

Some take the immutability claim further. For them, functional programming requires purity of functions, also known as referential transparency — a lack of globals and a lack of side effects. While this purity forms the central tenet of their functional programming, a language like Lisp, the prototypical functional language, has immutability but doesn’t prevent side effects.

Finally, some people think it means using a particular style of programming called Reactive, a set of monads from the functional programming world that are grafted object-oriented languages with libraries such as RxJava and ReactiveCocoa.

This list of defintions itself isn’t complete, but provides a rough outline of the surface of functional programming. Certainly, the variety of styles available even within functional programming belies the blurriness and complexity of the field.

There’s a few of lessons to learn from a list like this. First, people define functional programming in terms of the elements of their favorite functional language or, in some cases, style. If they’re Haskell writers, referential transparency might be the component they focus on. If they’re writing Reactive Cocoa in Swift, that particular mode of programming defines what functional programming is for them.

Second, each of these definitions implies a different prescription for what makes good code. In each case, the practitioners make an argument for why their particular style of functional programming will solve your problems. It’s clear, however, from the breadth of different functional styles and values that there’s no one “real” functional programming. Anyone claiming to sell you the One True Solution to your programming woes should be scrutinized.

Lastly, and there seems to be no way around this: programming is complex. Whatever style of programming you like to use, you’re going to run into complexity. Whether your language lays that complexity bare (like FP), or gives you the tools to abstract it away (like OOP), you’re going to have to roll up your sleeves and apply elbow grease. No programming style will make that go away.