Higher Order Function: Diving into the Functional Style of Scala

Reading Time: 3 minutes

Hi, community in this blog we are gonna talk about one very important feature of Functional style programming in Scala so make your IntelliJ ready and let’s learn about Higher-Order Functions.

Before going into Higher Order Function first let’s take a brief understanding of Functions in Scala.

Functions in Scala

As we all know, a function is a group of statements that performs a particular task.

How will you know that you have to use a function?

When a particular code is repeating itself again and again in your program then you have to consider enclosing that piece of code into a function.

Let’s create a simple program for performing addition between two numbers:

object function {
  def add(x: Int, y: Int) : Int = {  
    x + y
  }

  def main(args: Array[String]): Unit = {
    println(add(210, 100))
  }

}

Output: 310

In Scala, functions are treated as first-class citizens which means that you can assign a function to a variable and that is done using Anonymous Function (lambda). For example:

object function {
  var add = (x: Int, y: Int) => x + y

  def main(args: Array[String]): Unit = {
    println(add(210, 100))
  }

}

The above program will also give the same Output: 310

Now as we have understood the concept of Functions in Scala let’s move into the Higher-Order Function

What are Higher Order Function

Those functions can take a function as an argument and also can give a function as result.

Let’s take an example in which function is taking a function as an argument

object demoHigherOrder {
  val double = (i: Int) => i * 2               // Anonymous Function
  def demo(x: Int, y: Int => Int) = y(x)      // Higher Order Function

  def main(args: Array[String]): Unit = {
    println(demo(10, double))
  }

}

Output: 20

Explanation: The above program is an example of a higher-order function where we are taking a function as an argument. We have declared an anonymous function double which is taking an “int” and returning the double of that “int” and then we are passing any function named y(which also takes an Int and return Int) into our function demoHigherOrder as an argument along with x(which also takes an Int)

Then we are passing y over x as (y(x)) and in the main function, we are calling the higher-order demo with value 10 and the function double.

Function that Returns another Function

object Function extends App {
  def sayHello = (name: String) => {"Hello" + " " + name}
  var message = sayHello("Knoldus")
  println(message)
}

Output: Hello Knoldus

Explanation: In the above program we have a program function named sayHello and it’s equal to another function, therefore, we can say that it returns that function when we call sayHello but instead of returning the function it’s then invoked at the same time and it substitutes name with “Knoldus” and it will result in Hello Knoldus.

As we all know Scala allows Type inference therefore the message will also return a String since the function sayHello is returning a String.

Why to use Higher Order Function?

Higher-Order Function enables you to create control abstraction that allows you to reduce code duplication. Let’s take a real-life coding example to get the more clear picture.

Suppose you want to create an API that allows users to search for files matching some criterion like first you want to search for files whose names end in a particular string and your API looks like below:

  object FileMatcher {
    private def filesHere = (new java.io.File(".")).listFiles
  
    def filesEnding(query: String) =
      for (file <- filesHere; if file.getName.endsWith(query))
        yield file
  }

So far so good but now your user is asking for the feature that lets people search based on any part of the file name. So you add this feature to your API and your code looks like this:

  def filesContaining(query: String) =
    for (file <- filesHere; if file.getName.contains(query))
      yield file

It’s been some time and your API is working absolutely fine but now you want to search based on regular expressions.

Higher-Order Approach

Now here an experienced programmer will notice all of this repetition and wonder if it can be factored into a common helper function and will follow a higher-order approach and try to demonstrate the way in which first-class functions can help you eliminate code duplication where it would be very difficult to do so without them as shown below:

    object FileMatcher {
      private def filesHere = (new java.io.File(".")).listFiles
  
      private def filesMatching(matcher: String => Boolean) =
        for (file <- filesHere; if matcher(file.getName))
          yield file
  
      def filesEnding(query: String) =
        filesMatching(_.endsWith(query))
  
      def filesContaining(query: String) =
        filesMatching(_.contains(query))
  
      def filesRegex(query: String) =
        filesMatching(_.matches(query))
    }

In the above program, the function literal _.endsWith(_), used in the filesEnding method, means the same thing as:

  (fileName: String, query: String) => fileName.endsWith(query)

Conclusion

Thank you guys for making it to the end of this blog.

Via reading till now you must have the idea of how Scala’s rich function support building control abstractions. You can use functions within your code to factor out common control patterns, and you can take advantage of higher-order functions in the Scala library to reuse control patterns that are common across all programmers’ code.

Refrences

https://www.artima.com/pins1ed/control-abstraction.html

https://docs.scala-lang.org/tour/higher-order-functions.html

Written by 

Hi community, I am Raviyanshu from Dehradun a tech enthusiastic trying to make something useful with the help of 0 & 1.

1 thought on “Higher Order Function: Diving into the Functional Style of Scala4 min read

  1. I went over multiple sites for this info, landed on what I’ve been looking for, quite good.

Comments are closed.