The Function
object has been there since Scala 1.0 version. It provides some utility methods for dealing with higher-order functions. Despite the simplicity and usefulness of some of them I found that not only do many beginning developers not use it, but they don’t even know about them. In this post I would like to remind you about some of the functions I find useful in some cases.
chain
To get started let’s introduce 2 extremely simple functions from Int
to Int
. One of them, let’s call it inc
, will increase a number by one and the other one, double
, with multiply a number by 2.
1 2 |
|
Note: that for the both functions we could use shorter definition form like val inc: Int => Int = _ + 1
.
So what do we do when there is a sequence of these functions and we want to combine them? One of the most popular option in my practice is the following:
1
|
|
This piece of code takes a sequence of functions and combines them using andThen
method starting with the first one in the list and returning resulting function from Int
to Int
. It is by no means bad code. Personally I like it. Let’s see how it can be simpler with using chain
function from the Function
object:
1
|
|
It does exactly the same as the previous snippet but it might be more intuitive for the beginning developers. If we import all the functions from Function
object first it will be dead simple:
1 2 |
|
Note: If you want to use compose
instead of andThen
you still can do this with chain
by reversing the sequence:
1
|
|
tupled
Imagine there is a tuple of 2 elements, id and name, representing a user wrapped into Option
:
1
|
|
And a function, let’s call it auth
, which accepts id and name as two different arguments:
1
|
|
We can’t just map the auth
function over the user
because the former expects 2 arguments and our user is one tuple of 2 elements. One of the options would be extracting id and name and pass them as the separate arguments to the auth
function. It requires some boilerplate code to write. This is where we can use tupled
function from the Function
object. What it does is taking a function of let say 2 arguments and convert it to a function taking a tuple of 2 elements with the types of the initial arguments. That’s exactly what we need to map over the auth
function:
1 2 |
|
There are tupled
functions defined for tupling functions of arity from 2 to 5 inclusive. I rarely use tuples with elements more than 2 or 3 so I find it convenient.
Technically in the previous example the function tupled
was called on the function itself (as it’s defined both in the Function
object and Function*
traits). Another “trick” that can be useful is mapping over a map in what many people would say a natural way. (Also it demonstrates using the tupled
function from Function
object and not defined in Function*
trait). In Scala you can’t write code like this:
1 2 3 4 5 6 7 8 9 |
|
What many developers would do is something like this:
1 2 |
|
You can achieve the same using the tupled
function:
1 2 |
|
Maybe not so useful but helps to understand its application.
unlift
To illustrate the usage of unlift
let’s write a function that takes an Int
and returns Some(x)
if x is equal or greater than zero and None
otherwise:
1
|
|
What unlift
function does is it turns a function A => Option[B]
into a PartialFunction[A, B]
. It lets us to use our function in any place where partial function is required. To make it clear that’s how our function can be used to filter out the positive integers in the list:
1 2 3 |
|
I don’t use this on a daily basis but there are some cases like this when it comes very handy.
Bonus: there is an opposite function defined in PartialFunction
called lift
. To see how it is related to unlift
function the following equation is always true:
1 2 |
|
uncurried/untupled
These functions are the opposite to curried
and tupled
respectively. I didn’t see them used as much as the functions described above.
Although there is nothing new I found that it’s easy to forget about some useful API provided by Scala standard library. I hope this reminder is on time and can save you a couple of lines of code now or in the future.