Scala Functions – Higher Order Functions & Function Literals

Higher Order Functions are supported by many languages including Haskell, Scala, F#, Go, Javascript. Higher Order Function is a fancy name for a function which accepts functions as parameters.!! How is that? Well – that is because functions in Scala are treated as first class values – that means in Scala they can be assigned as values, passed as parameters and returned from functions.

Functions are said to be higher order functions if they do atleast one of the following

  • Accept functions as parameters
  • Returns functions as a result

The map function is one of the most popular higher order function.  Most Scala programmers have come across this function in their lives.

Before we get any deeper into functions – let’s look at another type of functions called function literals. They are more famously known as anonymous functions. Function literals are functions which do not have any name and are created, passed and returned from other functions or they can also be stored in variables.

Anonymous functions” being a simple name the question which comes to mind is “Why call it a function literal?” – The answer lies in the fact that Scala treats functions as first-class values. Let’s take an example

val str = "Hello World!"

In the above line expression on the right hand side of equal to sign “Hello World” is called a string literal which is assigned to a variable called str.

Applying the same principle a function can be assigned to a variable like this

val multiplyBy2 = (x:Int) => { x * 2 }

//Prints 20
println(multiplyBy2(10))

The expression on the right-hand side of equal to sign i.e the function (x:Int)=>{ x * 2 } is called the “function literal” which is assigned to a variable multiplyBy2. The function also does not have a name hence is also called an anonymous function.

Well that is out of the way, let’s look at function literals in more detail.

Passing functions as parameters

Anonymous functions behave the same way as regular functions. They take a one or more parameters, apply some logic and return a value. They are usually passed as parameters to other functions.

Refresher: Function accepts or returns functions as parameters is called a Higher Order Function

For example, if you have a list of cities and you want to count the length of the names of the cities and return a list of length of city names. Let’s first look take look at how we will write this code using the imperative way and then see a series of iterations to apply anonymous functions and higher order functions..

val cities = List("London", "New York", "Paris", "Rome")
var citiesLen = List()
def getCityLength(str:String):Int = {
  return str.length
}

for (city<-cities){
  cities.append(getCityLength(city))
}

Let’s use a more Scala way. Let’s switch from using a function to using a function literal.

val cities = List("London", "New York", "Paris", "Rome")
var citiesLen = List()
//Right hand side of the equal to sign is a function literal
val getCityLength = (str:String):Int=> str.length

for (city<-cities){
  cities.append(getCityLength(city))
}

A bit more Scala – We will only be using the function getCityLength only once to pass it to the map function. Hence let’s just pass the function literal directly to map operator instead of using a for-loop. The map

val cities = List("London", "New York", "Paris", "Rome")
val citiesLen = cities.map(city=>city.length)

Finally, stretching it, use placeholder _ in the function literal. This step is an optional step and is more for writing less code. Though it may be difficult to understand for some. But the logic and the result is still the same

val cities = List("London", "New York", "Paris", "Rome")
val citiesLen = cities.map(_.length)

Observe how we have reduced a 9 line code to a 2 line code but it still does the same job for us. It may seem like a whole lot difficult to write function literals/anonymous functions but if you follow the above approach for a few of the functions. This useful feature will help in reducing the amount of code which is being written.

Let’s now see how we can write our own function which accepts a function and processes it. The function below accepts three parameters

x, y which are integers and a function parameter called myFunction. It accepts an Int and returns an Int

def sum(x:Int , y:Int, myFunction:Int => Int) :Int = {
 val result = myFunction(x) + myFunction(y)
 result
}
val multiplyBy2 = (i:Int) =&gt; i*2
val add10 = (i:Int)=&gt;i+10

//Pass a function to multiply integers by 2
val result1 = sum(10,20,multiplyBy2)

println(result1)

//Pass a function to add 10 to each of the integers
val result2 = sum(10,20,add10)
println(result2)

//Pass a function to square each of the integers before adding
val result3 = sum(10, 20 , x=>x*x )
println(result3)

Returning function as a Result

In the previous example we saw how we passed a function literal to a higher order function and it helped us reduce the amount of code. Let’s now try and write our own higher order function which will return a function as a result.

Refresher: Function accepts or returns functions as parameters is called a Higher Order Function

The trick to know in this case is that only a function literal – aka – anonymous function can be returned and not a regular function. See Below

def multiplyBy(m:Int) = {
  printf("Multiplier is %d \n", m)

  //Return the function.
  (x=> x * m)
}
val multiplyBy3 = multiplyBy(3)
//Prints function1 because the function multiplyBy
//returns a function
println(multiplyBy3)

//Prints 30
println(multiplyBy3(10))

This function can be simplified a bit more if we remove the print statement.

def multiplyBy(m:Int) = x => x * m

val multiplyBy3 = multiplyBy(3)
//returns a function
println(multiplyBy3)

//Prints 30
println(multiplyBy3(10))

val multiplyBy5 = multiplyBy(5)

//Prints 50
println(multiplyBy5(10))

//Prints 60
println(multiplyBy5(12))

Next entry is about Currying – Till next time!

Leave a Comment