Now after we have considered basics of Scala functions, we can make a next step in more complex use cases functional programming. Since functions in Scala are objects we can pass them as arguments in another 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 accept another functions 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

At 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 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:

scala-function-as-parameter

Of course you need to declare all of functions before their usage. A function passed as 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 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.

scala-function-callback

By passing a function as 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

Some times you don’t need to declare a function before its usage because it is need to be used just in one place. For this case anonymous functions suit well. Let’s use one of previous example 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 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 alias for anonymous function.

Function as return value

The most rare 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 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 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.

About The Author

Mathematician, programmer, wrestler, last action hero... Java / Scala architect, trainer, entrepreneur, author of this blog

Close