By: Serguey Martinez, Staff Engineer, TribalScale
At first, I didn’t see my teammates using some functional tools and patterns that swift provides. I didn’t know either that those patterns existed!
Don’t get me wrong, my team mates write quality code…
I saw nice structured code and just the right amount of “if lets”, “guard lets” and “?”
Higher order functions
Functions in Swift are special citizens; meaning that you can pass functions to other functions, they can return functions, or they can hold other functions in their pouch, like kangaroos.
Let me walk you through a perfect example to demonstrate why this is so incredible and why I love functions.
Let’s start with a simple case, and say I need a function called addOne.
Simple, but not very interesting. The problem is that some enthusiastic mind asked for an addTwo feature.
Okay, no problemo, gist please:
That was easy!
But my grandpa has trouble doing simple calculations and he is asking for an addThree function; it will be very useful for when he goes to play cards with his friends.
I also have friends in the financial sector that would pay high sums for an add284 function!
You see where I’m going?
So, how can I create any function that I want, such as add284, but with the same function that creates addThree?
partialAdd is a function applied in two steps, or a function that returns another function.
It’s a clever way to refactor our code, but how can addTwo, addThree or addALot remember that it is a 2, a 3 or a 284 of numbers it has to add?
Well, because of closures.
Closures sounds like a fancy term, but it’s the glue that sticks partialAdd with all the other functions that it generates. Every function that is generated from partialAdd, will have direct access to objects and values that were passed or created to/in partialAdd.
And it doesn’t matter if I use addThree, 2, 5 or 100 times, it will always have access to the 3 we passed to its creator at the start.
Imagine a rope or a lasso being thrown at partialAdd to get the input values as if those nostalgic functions were longing for them since they were conceived. Poetic.
Yesterday I received a call from my friend at the zoo. He has problems with counting the zebras, and he needs to check everyday just in case any zebra is missing or mistaken for a crosswalk.
He wants to use the functions addOne, addTwo and maybe more in conjunction. So, I told him that he could do some composition with the functions he already has.
But there is another way that he might like, as it’s easier to read and you can expect that functions will be executed from left to right, the opposite of the example above.
Pipe is just another function using partial application and closures, with small differences:
- the inner function (the function that is returned first) inside pipe will have access to an array of fns that was fixed instead of a simple Int. Remember closures.
- we are passing functions in the first step. Higher order functions can accept other functions as parameters.
- pipe is still a partial application but it is immediately invoked in the same line with the syntax “(fn1, fn2)(Int)”
We iterate through every function in the pipe, one at a time. With reduce, we can apply functions, passing values that were calculated in the previous loop and return a new value that the next loop will use.
My friend was impressed: we had found an elegant way of composing functions.
Pipe as a generic
Pipe can be widely used if we convert it as a generic.
Imagine the possibilities!
We could even write a library that composes HTML, request strings or something more procedural that could go deeper into category theory (out of the topic today), for example:
I’ll leave it there for now - I hope it was fun and informative!
Serguey Martinez is a Staff Engineer at TribalScale. He is passionate about functional programming.
TribalScale is a global innovation firm that helps enterprises adapt and thrive in the digital era. We transform teams and processes, build best-in-class digital products, and create disruptive startups. Learn more about us on our website. Connect with us on Twitter, LinkedIn & Facebook!