Tutorials Hut




  •  Higher order functions(HOD), Currying, Pattern Matching and Sealed Class 

    In this article we will look into Scala higher order functions(HOD), Currying and Pattern Matching.

    Higher Order Function In Scala (HOD)
     A higher order function is such a function which can take a function as input or return another function as return type. Scala is a functional programming language and so everything in Scala is a function.

    Good example of HOD in scala API is a map function where we can pass functions and do operations without mutating the state of variables.

    Example of HOD function with map:

    object HOD {
     
      val myDoubleFunction: Int => Int = (x: Int) => x*2
     
        def main(args: Array[String]): Unit = {
    	val intList = List(1, 2, 3)
    	val doubledIntList = intList.map(myDoubleFunction)
    	println(doubledIntList)
      }
    } 

    Output

    List(2, 4, 6)

    Example of HOD which takes Function as Input

    doOperation function takes a function and data as input.

    object HOD {
     
      val myDoubleFunction: Int => Int = (x: Int) => x*2
     
      //HOD functions takes a funcion as input
      def doOperation(dataF: Int => Int, input: Int) = {
    	dataF(input)
      }
     
      def main(args: Array[String]): Unit = {
    	println(doOperation(myDoubleFunction, 10))
      }
    } 

    Output

    20

    Another Example of HOD Which Returns Function

    Here giveMeOperationFunc returns another function as output.

    object HOD {
     
      val myDoubleFunction: Int => Int = (x: Int) => x*2
      val myTripleFunction: Int => Int = (x: Int) => x*3
     
     
      //HOD functions takes a function as input
      def doOperation(dataF: Int => Int, input: Int) = {
    	dataF(input)
      }
     
      def main(args: Array[String]): Unit = {
    	//println(doOperation(myDoubleFunction, 10))
    	println(giveMeOperationFunc("double"))
      }
     
      def giveMeOperationFunc(op: String) = {
    	if(op.equals("double")) {
      	myDoubleFunction
    	}
    	else {
      	myTripleFunction
    	}
      }
    }

    Output

    HOD$$$Lambda$1/1915910607@7dc36524

    Currying

    Currying is a concept in functional programming where a function can have two arguments and we can call them separately and finally return the result.

    Example:

    sumUsingCurry function takes two arguments (a: Int)(b: Int) and we can call one by one to do the final sum of a and b.

    object Currying {
     
    def sumUsingCurry(a: Int)(b: Int) = a+b
     
      def main(args: Array[String]): Unit = {
    	val firstPartCalled = sumUsingCurry(10)_
    	val sum = firstPartCalled(20)
    	println(sum)
      }
    } 

    Output

    30

    Scala Pattern Matching

    In OOP or other programming languages we always use if-else blocks to make decisions, Scala and functional programming discourages this practice and promotes the use of pattern matching as much as possible in similar scenarios.

    Pattern matching is done using case and match in Scala, we try to match data and based on match we return different output. In scala case and match both are reserved keywords.

    Example 1:

    In the below example see we are matching rollNumber and based on the match returning name related to that roll number, also look ‘case _’ where if no match a default is returned.

     

    object PatternMatching {
     
      def main(args: Array[String]): Unit = {
     
    	var rollNumber = 104
    	val name = rollNumber match {
      	case 101 => "Alex"
      	case 102 => "Jon"
      	case 103 => "Ron"
      	case 104 => "Tom"
      	case _ => "Unknown default"
    	}
    	println(name)
      }
    }

    Output

    Tom

    Example 2:

    Pattern matching on String values.

    object PatternMatching {
     
      def finNumber(name: String) ={
    	val number = name match {
      	case "Alex" => 101
      	case "Tom" => 102
      	case _ => 100
    	}
    	number
      }
     
      def main(args: Array[String]): Unit = {
    	println(finNumber("Alex"))
    	println(finNumber("Unknown"))
      }
    }

    Output

    101
    100

    Pattern matching on Case Class

    Pattern matching on case class, see below example where we are passing student case class object to find field of that student. In case when the student is unknown and no match default Unknown is returned.

    Example:

    object PatternMatching {
      def findField(student: Student) ={
    	val field = student.name match {
      	case "Alex" => "Art"
      	case "Tom" => "Science"
      	case _ => "Unknown"
    	}
    	field
      }
     
      def main(args: Array[String]): Unit = {
    	println(findField(Student(101, "Alex")))
    	println(findField(Student(101, "XYZ")))
      }
    }

    Output

    Art
    Unknown

    Pattern matching on Type

    We can also do pattern matching on case class or class types. See below example where we have Student and Cow case classes and based on their type match we are returning string output.

    Example:

    case class Student(rollNumber: Int, name: String)
    case class Cow()
     
     
    object PatternMatching {
      def findType(obj: Any) ={
    	val field = obj match {
      	case obj: Student => "Student type"
      	case obj: Cow => "Cow type"
      	case _ => "Unknown"
    	}
    	field
      }
     
      def main(args: Array[String]): Unit = {
    	println(findType(Student(101, "Alex")))
    	println(findType(Cow()))
      }
    }

    Output

    Student type
    Cow type

    Sealed Class or Trait

    A class or train in scala can be marked sealed using the “sealed” keyword. It ensures that all sub classes or subtypes are declared within the same file, this is useful if we want to keep all related classes to that trait in the same file.

    Example:

    All subclasses of Student class should be in the same file else it will give error.

    sealed abstract class Student
    case class ArtStudent() extends Student
    case class ScienceStudent() extends Student

    Reference

    Next Article

    • Scala Exceptions and Options

















  • Leave a Reply

    Your email address will not be published. Required fields are marked *