One of the core concepts that has driven my quest for knowledge about programming techniques has always been my own laziness. After all, what attracted me to computers back when I first started playing with them was the notion that they could do things for me. All I had to do was sit back and tell them what I wanted.
But I quickly learned that computers were very literal. Unless I told them exactly what I expected in explicit and unambiguous terms, using a language that they understood, they would rarely give me back what I had in mind. And being lazy, I didn’t want to work any harder than I had to, to express my intentions.
I started to look for ways to make coding easier and more fun. And that search led me directly to functional programming.
New Ways to Look at Problems
I was first introduced to functional programming when I was a senior front-end engineer working at a small start-up in San Francisco. One day, a programming wizard who labored deep in the bowels of the company’s research group heard me complaining about some of the messy state-dependent code I was working on, and lured me into a conference room with fancy promises. There, he proceeded to give me an impromptu three-hour introduction to Haskell, a classic functional programming language, including a cursory explanation of the philosophy of functional programming.
That promise kept me going as I started to dig into this exotic realm. I believed that functional programming techniques could offer me better ways to break a problem apart and solve it in tiny, focused bites. I was thrilled by the possibility that I could make my code cleaner, more portable, more manageable, more readable, and easier to maintain.
Higher Order Functions
Using higher-order functions is the first step toward thinking about your code as a set of independent single-task components that can be taken apart and put back together in different ways to solve different problems. A function can easily be written to call any other function just by passing it in and then calling it during execution, optionally returning a new function to be called again at a later time. Since functions are passed by reference, they carry their context with them in closures, so they can operate within the state that existed at the time they were called rather than relying on the shifting possibilities of an external state.
Pure Functions with No Side Effects
Functional programming also brings with it some strong opinions about how functions should be written. A pure function in functional programming is the ideal. Pure functions don’t interact with any variables that exist outside of themselves. They don’t make any changes to variables not defined in their own scope, and they don’t rely on external values other than those passed in as parameters.
Pure functions always return the same result when given the exact same set of inputs, making it easier to create robust and reliable tests. That means that you can count on the result from a function staying the same as long as the parameters you pass in are the same. That also allows you to do some optimizations such as memoization, avoiding complex calculations by storing results in an array inside of a function and checking against that array before doing the calculations when a new input comes in.
Composition and Decomposition
Another advantage of pure functions is that they perform one task and return one result. With careful naming, these pure functions become almost self-documenting. And the more you build your code out of independent single-task functions, the less deeply nested complexity you need to maintain and document. Your challenge becomes thinking about how to break your problem into small bite-sized pieces, and then compose them together in sensible ways.
Newer features in ECMAScript 2015 and beyond include the convenience of arrow functions that make it easier and more intuitive to write code with anonymous in-line functions. The destructuring and spread operators also make it easier to work with arrays that may contain an unknown number of elements at the time they’re called. And generators give us native access to some of the magic of lazy evaluation, just like our friends who use Haskell and Ruby have been doing for years.
A New Way to Learn Functional Programming
As I started applying functional techniques, I saw my programs, my problem-solving skills, and my relationships with my fellow engineers improve. My code was cleaner, more self-documenting, and easier to maintain and discuss. And I was doing less work and enjoying the process more.
I hope you go out and explore different programming techniques that work for you and your team. If you’re curious about the benefit in using functional techniques, instead of wondering, instead give the course a try, and let me know how it affects your code, your thought processes, and your professional relationships. It had significant impacts in not only my work but also my professional career. I think you’ll find that adding functional problem-solving to your programming stockpile isn’t just lazy, it’s also productive and fun.
Become a developer who knows the difference between functional and imperative code.
Become a developer who can switch between Object-Oriented Programming and functional.
Recognize when it’s better to use on technique over the other.
Here’s how: I’ll show you with my functional programming course. Add recursion, composition, mapping, and more to your development tool belt to make your code easier to read and less repetitive.
- What is Functional Programming?
- Working with Recursion
- Understanding Currying
- Map, Reduce, and Filter
- Functional Compositions
- What We’ve Learned