Now after we have considered basics of Scala functions, we can make the next step in more complex use cases functional programming. Since functions in Scala are objects we can pass them as arguments in other functions, also we can return them as a result. In this article, I’m going to examine multiple examples of higher-order functions.

What functions? A function which accepts another function as arguments or returns a function is a higher-order function. It sounds like a madness if you have a previous experience with object-oriented programming, but after the reading, you’d definitely understand how it works.

Function as Parameter

First, let’s do what we already know how to do – declare a simple function.

def halfMaker(value: Int): Double = value.toDouble/2

This is a small function with a trivial logic: accept Int value and return a half of it in a Double type.

What about one more simple function?

def addFive(value: Int): Int = value+5

addFive function even more trivial than the halfMaker. It accepts Int value and adds to it 5.

What is common in these two functions? They both accept Int parameter and return an AnyVal value. So in general, we can describe these functions by the following signature Int => AnyVal.

Now let’s declare a function which has a function argument among other parameters.

def processRange(start: Int, finish: Int, processor: Int => AnyVal): Unit = {
 for (i <- start to finish)
 println(processor(i))
}

As you see processRange for each Int value between the start and finish, applies the processor function and prints a result. The type of the processor parameter is Int => AnyVal. It matches the signatures of two first functions which we declared earlier in the article.

Here is a demonstration of this code in action:

Image titleOf course, you need to declare all of the functions before their usage. A function passed as an argument to another function is a callback function.

Let’s continue with one more example of callback functions in Scala.

def moneyTransfer(amount: Double, providerFee: Double => Double): Double = {
 amount + 10 + providerFee(amount)
}

def providerA(money: Double) = money * 0.05

println(moneyTransfer(100, providerA))
//The output is 115.0

This code isn’t good from the functional point of view, it doesn’t check that the amount is positive and more than 10 etc, but this example is just for demonstration of a callback function.

So let’s assume that we have an application which works with money transfers. We are a service provider. If people want to send money, they come to us and we give them an interface for this. In our turn, we use already existing services for this, e.g. Provider A, Provider B etc. Our fee is $ 10. Depending on the provider, an extra charge occurs and they vary from provider to provider.

The moneyTransfer function accepts two arguments: amount – amount of money which customer wants to transfer and providerFee is a callback function with signature Double => Double. The purpose of moneyTransfer function is to calculate total which customer needs to provide in order to make a transfer.

Image titleBy passing a function as the argument you inject an extra logic inside of the higher-order function. So it’s very powerful mechanism to make you code more flexible and efficient. In the same time, you can complicate a simple code by redundant callbacks usage.

Anonymous Function

Sometimes you don’t need to declare a function before its usage because it needs to be used just in one place. For this case, anonymous functions suit well. Let’s use one of the previous examples for demonstration:

def moneyTransfer(amount: Double, providerFee: Double => Double): Double = {
 amount + 10 + providerFee(amount)
}

println(moneyTransfer(100, moneyTransfer(250, m => m / 10)))
//The output is 285.0

So instead of declaring a regular function with signature Double => Double, we directly passed the anonymous function m => m / 10. The type of m is omitted because it can be defined based on the context where the anonymous function is invoked.

//Also valid
moneyTransfer(100, moneyTransfer(250, (m: Double) => m / 10))

Sometimes an anonymous function is called lambda function. So you can use this name as an alias for an anonymous function.

Function as Return Value

The rareest case of higher-order functions is when a function returns another function. When it’s handy? If to been honest, I still don’t know good use cases for this. But Scala gives you the chance to do this.

So let’s consider the following example:

def getStrategy(enoughEnergy: Boolean) = {
 if (enoughEnergy)
 (energy: Double) => "We are going to attack with damage "+energy
 else
 (energy: Double) => "We are going to reflect damage "+energy/2
}

val returnedFunction = getStrategy(true)

returnedFunction(15.0)
//We are going to attack with damage 15.0

That’s how a function can be returned as a result.

Summary

Now you know how to use higher-order functions. Maybe it’s hard to start to use them almost instantly after the reading of this article, but I believe that you will be able to read and understand a code where higher-order functions are used. The easiest part of the blog post is about anonymous functions. They are compact and behave like normal functions, except that circumstance that they don’t have names.