Function Composition
The last piece of the functional puzzle I am going through is function composition. It combines pure functions, first class functions and currying together into one thing. You can think of it as putting small pieces together to create a larger piece. Like a composer putting notes together to create
Really all function composition means is that you combine functions in order, taking the output of the first, and passing it to the second and so on until you run out of functions to call. The result is then passed back to the caller. If you are familiar with writing scripts in a terminal you may know this as piping
output into another script.
Do we go down, down, left or right?
There are two ways of thinking about composing functions. The most common way you will see it is actually running backwards through the arguments. You can think of this as the maths way due to it being how mathematics symbolises functions - for example f, g => f(g(x))
- where g
is actually run before f
.
The opposite of this is the piped way, where you run the functions in the order you specify them. This looks like f, g => g(f(x))
.
Both end up with the same result, and you will often see both options availabile with libraries for functional programming. Pick whichever you like more.
Basics
Lets look at some basic string manipulation you may want to do that is perfect for function composition. Strings in javascript are actually immutable, meaning they are a great way to learn about functional programming.
Lets say we have a persons full name, and we want to return it as only the first name with an uppercase first letter.
We could easily create another function to call these in order as we have done with getFirstNameCapitalised
, but as we use composition more and more it would be create to have a tool to automatically do that part for us. We know our functions take one input and return one output so lets use this to our advantage. Lets assume our compose / pipe
functions already exists and go straight to how it would be used.
Now all our getFirstNameCapitalised
functions do the same thing. They each take a string name
parameter, call getFirstName
, and pass the result of that into the first parameter of capitaliseFirst
. The output of that is then the final returned value.
Lets try and implement a simple version of this. We will only accept a single input parameter, and then call every function in our list until complete. There are more complex versions which accept more parameters, calls with no parameters etc. but we are trying to keep things simple for now.
Alright that looks a little tricky but following it step by step it is actually pretty simple. We use reduce
here because it is an inbuilt function for javascript arrays that gives us the returned value of the last loop.
Note: To build compose
rather than
pipe, just use reduceRight
instead, or reverse
the functions array.
You can step through the code below to see it in action!
A bit more complexity please!
So we have our simple pipe working, now time to get into the juicy stuff!
Did you realise that it now doesn’t matter how we group or nest composes! This means that we can separate out functions into meaningful blocks.
For instance - all the pipe
functions below return the same result for the same input. One pipe is as good as another!
You can also split different pipes into variables if you find it helps documentation and supporting. The sayHiToCapitalised
does exactly the same thing as the three examples above. All we have done is give more detail on what we are doing.
Conclusion
That is it for what I think is important when first learning about functional programming in Javascript. These are great ideas that you can include anywhere you write code. It doesn’t have to be separated into object oriented or not. Just use the tools available to you to write better code.
What to read more? Check out more posts below!