Learning functional programming can be challenging. It involves concepts like monads, functors, and others. On top of that, your team must be on board with applying functional programming to reap the benefits.
There are, however, lessons you can start applying without the need to understand more advanced concepts and have the buy-in of the whole team.
These tips from functional programming are easy to understand, and you can start using them to improve your code right away.
It helps is to start thinking of your functions in terms of funnels that transform data rather than a set of imperative operations. Input comes in, then you apply a set of transformations and return transformed output.
It’s also where function chaining comes into play. Function chaining refers to the concept of chaining multiple functions in a row by using the output of the previous function to call the next one. It’s similar to method chaining from object-oriented programming.
Function chaining often makes your code cleaner and less repetitive. It removes extra variables at each step which saves you from the cognitive effort of naming those variables. Function chaining is often great for the transformation of collections, such as arrays.
Let’s look at two approaches for solving the same problem. Let’s start with an imperative one that uses a
Now let’s see the same function rewritten using function chaining:
As you can see function chaining results in more compact code, and we avoided having the intermediate
Not all of your functions will be fit for function chaining, and that’s okay. Apply it where you can and avoid overengineering your code to fit the pattern.
Pure functions are functions that always return the same output given the same input. Another distinctive characteristic is that they cause no side effects outside of the function scope.
Pure functions are closely associated with the concept of immutability . Since mutating an input object is clearly a side effect, you should avoid it if you want your functions to be pure. A way to solve it is by copying the input parameters before mutating them. This way, the original input parameter stays unchanged.
The advantages of pure functions:
- Reliability - you are can always count on pure functions to return the same output given the same input.
- Testability - Since pure functions do not create any side effects or mutate input, you can run them multiple times in your tests without worrying about the state.
Point-free style means that the arguments of the function are not explicitly mentioned when it is being called.
You create functions through the composition with simpler ones that transform your data. As a result, your functions are more modular, and your code ends up being more declarative.
Essentially, you don’t describe how the function works, only what it does to the input. It also avoids temporary variables that can be a source of confusion or bugs.
Point-free style works pretty well when combined with function chaining.
Let’s rewrite our earlier function chaining example and apply the point-free style:
Notice how we passed the
getName function to map and filter without explicitly specifying its input parameters.
When you discover point-free style, it might be tempting to start using it everywhere to make your code concise. Just remember that it also comes with trade-offs.
Point-free can hurt the flexibility of your code if taken too far. In some cases, you might have to completely restructure your functions because of minor requirement changes.
Currying is a transformation technique that transforms a function with multiple parameters into chained functions, each accepting one parameter. Doing so allows creating more specialized functions by applying some of the arguments ahead of time.
When you have a function with multiple parameters, and you catch yourself repeating some of the parameters multiple times, you can manually curry the function and create a more specialized one.
In this post, we went over some of the functional programming concepts you can immediately start applying.
Admittedly, the examples of this post are contrived to make the concepts easier to understand. For example, we manually created a curried version of a specific function which often doesn’t scale.
Integrating functional programming in your projects is much easier with the help of functional programming utility libraries such as
. Among many other useful utilities, Rambda.js has a
curry function that helps create curried versions of functions.