What is Function in Scala and its Types:

Reading Time: 6 minutes

Scala is a partial functional programming language so function plays an important role. A function is a collection of statements that perform a certain task. The function makes it easier to debug and modify the code. Scala functions are first-class values. Scala functions are first-class values. You must mention the return type of parameters while defining the function and the return type of a function is optional. If you don’t specify the return type of a function, the default return type is Unit. We use keyword def for function declaration.

How to declare function in Scala:

def functionName(parameters: type of parameters): return type of function = {
             //statements to be executed 
           }

Types of Functions in Scala:

Scala has the Following types of Functions:

1.) Anonymous Function:

In Scala, an anonymous function is a function that has no name and works like a function. An anonymous function is also called a lambda function. This can be useful when we need to provide a piece of code as a parameter to another function. We can create an anonymous function either by using the => symbol or _ (underscore) wild card in Scala.

Syntax of Anonymous Function:

(a:Int, b:Int)=> a*b
       
       Or

(_:Int)*(_Int)

In the above first syntax, => is a transformer. In the first syntax above, => is a transformer. The transformer is used to convert the parameter list to the left of the symbol into a new result using the expression on the right.

In the above second syntax, _ (underscore) character is a wildcard is a shorthand way to represent a parameter who appears only once in the anonymous function.

In Scala Anonymous functions are two types:

i.) Anonymous Functions With Parameters:  

If an anonymous function is assigned to a variable, we can invoke that variable as a function call. We can define multiple arguments in the anonymous function.

Let’s see by an example:

object AnonymousFunction 
{
    def main(args: Array[String]) 
    {
          
        var function1 = (FirstNumber:Int, SecondNumber:Int) => FirstNumber + SecondNumber
        var function2 = (_:Int) + (_:Int)

        println(function1(4,2))
        println(function2(12,22))
    }
}

In the above example, function1 is a function with multiple parameters.

ii.) Anonymous Functions Without Parameters:

In Scala, we can define an anonymous function without parameters to pass an anonymous function as a parameter to another function.

object AnonymousWithoutParameter 
{
    def main(args: Array[String]) 
    {
        var function1 = () => {"Welcome to Knoldus Blogs."}
        println(function1())
          
        def myfunction(category:(String, String)=> String) = 
        {
            fun("Scala", "Akka")
        }
          
        val add = myfunction((str1: String, str2: String) => str1 + str2)
        println(add)
    }
}

In the above example, function1 is an anonymous function without a parameter and myfunction is a function that contains an anonymous function as a parameter.

2.) Closure Function:

Closures are functions that use one or more free variables and the return value of this function is dependent on these variables. Free variables are defined outside the closure function and are not included as parameters to this function. So the difference between a closure function and a normal function is the free variable. There is no value for free variables in functions.

Example:

object Addition
{
    def main(args: Array[String])
    {
        println( "Sum1 = " + sum(1))
        println( "Sum2 = " + sum(2))
    }
          
    val a = 4
    val sum = (b:Int) => b + a
}

In the above example, we can see that Val a is a free variable and sum is a closure function.

3.) Recursion Function:

A function calls itself either directly or indirectly and the corresponding function is called a recursive function. It breaks the problem into smaller sub-problems and calls itself for each of the problems. That is, it simply means function calling itself.  Recursion is quite common in functional programming and provides a natural way to describe many Algorithms. Recursion is an important concept of Functional programming. Scala supports Recursion very well.

Let us understand recursion using the example:

object Factorial
{
    def fact(n:Int): Int=
    {
        if(n <= 1) 1
        else n * fact(n - 1)
    }
      
    def main(args:Array[String])
    {
        println(fact(5))
    }
}

The above code is demonstrated in a recursive approach to a factorial function, where the condition n == 1 results in a break from the recursion.

Tail Recursion:

A recursive function is said to be tail-recursive if the recursive call is the last thing done by the function. The tail-recursive functions are considered better than non-tail recursive functions as tail-recursion can be optimized by the compiler.

There is no need to keep a record of the previous state.
Let us understand it by an example:

import scala.annotation.tailrec
  
object tailRecursion
{
    def factorial(n: Int): Int =
    {
      
        @tailrec 
          def factorialAcc(acc: Int, n: Int): Int =
            {
              if (n <= 1)
                acc
              else 
                factorialAcc(n * acc, n - 1)
          }
        factorialAcc(1, n)
    }
      
    def main(args:Array[String])
    {
        println(factorial(5))
    }
}

Here in the above code, we can use the @tailrec annotation to confirm that this function is a tail-recursive.

4.) Higher Order Function:

Higher-order functions are possible because the Scala programming language treats functions as first-class values. Higher-order functions are a function that takes other functions as parameters, or whose result is a function. These functions are also helpful in creating lambda functions or anonymous functions in Scala.

Let’s see an example of a Higher-order Function:

object HigherOrderFunction 
{
    def main(args: Array[String]) 
    {
      
        val numbers = List(4, 6, 8)
      
        def MultiplyValue = (y: Int) => y * 2
        val result = numbers.map(y => MultiplyValue(y))
        println("Multiplied List is: " + result)
    }
}

The above example of a higher-order function in which MultiplyValue is a function and map is another function that takes MultiplyValue as a function. A map is a higher-order function.

The higher-order function has two subtypes:

i.) Higher-order function with call-by-name.

ii.) Higher-order function with a call-back parameter.

i.) Higher-order function with call-by-name:

object CallByName 
{
  def main(args: Array[String]) 
    {
      def placeOrder(orders: List[(String, Int, Double)])(exchangeRate: => Double):       
    Double = {
  var totalCost: Double = 1.0

  orders.foreach {order =>
    val costOfItem = order._2 * order._3 * exchangeRate
    println(s"Cost of ${order._2} ${order._1} = £$costOfItem")
    totalCost += costOfItem

  }

  totalCost

    }
}

The Call-by-name function parameter exchangeRate: => double will evaluate any exchangeRate function every time it is called.

ii.) Higher-order function with call-back-parameter:

object CallByValue
{
  def main(args: Array[String]) 
    { 
      def printReport(sendEmailCallback: () => Unit) {
        println("Printing report ... started")
  
        println("Printing report ... finished")
        sendEmailCallback()
       }
         printReport(() =>
          println("Sending email ... finished")
        )
     }
 }

5.) Nested Function:

In functional programming, you should try to break down your logic into other smaller functions. But sometimes you have logic that is tightly tied to a particular function and Scala gives you the ability to nest functions so that you can still benefit from the functional style of coding. We can define functions inside functions and functions defined inside other functions called nested or local functions.

Let’s see an example:

object NestedFunction
{
    def main(args: Array[String])
    {
        println("Min and Max from 4, 6")
                maxAndMin(4, 6);
    }
    
    def maxAndMin(a: Int, b: Int) = {
     
       def maxValue() = {
          if(a > b)
          {
              println("Max is: " + a)
          }
          else
          {
              println("Max is: " + b)
          }
       }
     
       def minValue() = {
          if (a < b)
          {
              println("Min is: " + a)
          }
          else
          {
              println("Min is: " + b)
          }
       }
       maxValue();
       minValue();
    }
}

In the above example, maxAndMin is a function and maxValue is another inner function that returns the maximum value between a and b Similarly minValue is another inner function that is also a nested function, this function returns the minimum value between a and b Is.

6.) Currying Function:

Currying in Scala is simply a technique or a process of transforming a function. n other words it is a technique of transforming a function that takes multiple arguments into a function that takes a single argument. It is widely used in functional programming languages.

Let’s see an example:

object Currying
{
    def add(x: Int, y: Int) = x + y;
  
    def main(args: Array[String])
    {
        println(add(10, 12));
    }
}

The above in which we have to define add function which takes two arguments x and y and function just add x and y and give us a result, call it in the main function.

7.) Partial Function:

 a partial function is a function that accepts only a specific set of data as the input. It only provides an answer for a subset of possible data and defines the data it can handle. In Scala, a partial function can also be queried to determine whether it can handle a particular value.

Let’s see by an example:

object PartialFuction
{
  
    def main(args: Array[String])
    {
  
        val r = new PartialFunction[Int, Int] 
        {
  
            def isDefinedAt(q: Int) = q != 0
  
            def apply(q: Int) = 12 * q
  
        } 
  
        println(r(10))
    }
}

In the above example, two methods are defined to implement the partial function, where isDefinedAt returns the condition and if the given condition is met then performs the apply operation.

Conclusion:

In this blog, we have gone through the function and its types in Scala. I hope that this was informative and easy to understand, also, if you have any queries please feel free to list them down in the comments section. If you enjoyed this article, share it with your friends and colleagues. For more blogs, Click Here.

References:

https://www.tutorialspoint.com/scala/higher_order_functions.htm

Written by 

Aditya Narayan is a Software Consultant at Knoldus Inc. in Noida. He recently did his B.Tech in Computer Science and Engineering from Abdul Kalam Technical University. He is familiar with C, Html, CSS, Php, JavaScript, and SQL. His hobbies include watching movies, reading books, and traveling in his spare time.

Leave a Reply