What is functional programming?
As you probably got from the title up top, this blog approaches web development from the perspective of functional programming. Functional programming is a bit different from object-oriented or procedural programming, which is probably what most of you are doing right now.
Hold up, though. What’s functional programming? “I write functions in my programs all the time!”
Wikipedia gives this bone-dry definition:
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.
What does this mean? Let’s step through some of the principles of functional programming, together. It’s pretty cool, I promise.
What are the principles of functional programming?
I’m simplifying a lot, but here are the principles of functional programming I’ll cover in this series:
- Pure functions. Functions in functional programming languages are pure. They have no side effects — that is, they don’t change state or affect any part of your program beyond themselves. Pure functions always return the same value given the same parameters, no matter when you call it. Another term for this is referential transparency.
- Immutable data. Data in functional programs is immutable — once defined, it can’t be changed. If you need some new representation of data (such as a list of students filtered by degree program), you’ll get a remixed copy of the original value.
- Plain data structures. Data in functional programming languages is represented by plain data structures such as lists, arrays, or maps. Plain data structures are easy to generate, easier to send, and even easier to read. This differs from object-oriented languages, where data is represented by objects that each expose their own unique methods and properties.
- Recursion. Functional programs favor recursive functions over loops. Recursive functions are functions that call themselves (until they don’t).
- Statelessness. Functional programs are (mostly) stateless — they don’t keep track of time or take a snapshot of data that determines how later functions do their thing. Instead, data is fed into a pipeline of functions chained one after another that will always return the same result given the same inputs, no matter what time it is. Where state has to be maintained, it’s boxed out to specific corners of your program with a lot of warning flags.
Why write functional programs?
Here are some reasons why you might write functional programs:
- Easier to reason about. Because functions are pure and data is immutable in functional programs, it’s really easy to work out what the different parts of your program do. You don’t have to try to keep program state in your head or worry about if one part of your program is secretly messing with another part.
- Less code. Programs written in a functional style are often more succinct and expressive than programs written in a procedural or object-oriented style. This is especially true for languages like Clojure, which as a Lisp dialect has extremely minimal syntax and makes it easy to express complex functionality through the composition of simple self-contained pieces.
- Resistant to errors. Because functions are pure and data is immutable in functional programs, the common culprit for bugs — weird side effects, mangled state, functions called out of order, and action at a distance — don’t exist. Likewise, because the code itself is often much leaner than object-oriented or procedural code, there’s far fewer places for bugs to hide,
- Easier to maintain. Smaller codebases that are easier to reason about and resistant to bugs are easier to keep working. Plus, once you get the hang of functional programming, you can ship new features a lot quicker and be pretty confident they won’t jack up the rest of your program.
I’ll talk more about how functional programming gets us these benefits in the coming posts.
Next time: first-class functions!