Scala tutorials
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