Scala Implicit Function – How to use

In this post, we are going to see how to use Scala Implicit function.

Assume we have a case class “Employee” class which contains name, age, role and location fields and we have a list of Employee case class objects. Lets see how to use Implicit function to find out the employee details by age and also by location.



case class Employee(name: String, age: Int, role: String, location: String)

class EmployeeFunction(employees: List[Employee]) {

    def findEmployeesByRole(role: String): List[Employee] ={
        employees
          .filter(e  => e.role == role)
    }

    def findEmployeesByLocation(location: String): List[Employee] ={
        employees
            .filter(e  => e.location == location)
    }

}

object EmployeeFunction {
    implicit def employeeFunction(employees: List[Employee]):EmployeeFunction = new EmployeeFunction(employees)
}


In the above code, The “EmployeeFunction” contains an implicit function “employeeFunction” defined with “implicit” keyword. So the employee list is implicitly passed to this function.

Now, to use this function in other file, we have to import this function.
Here in the below code, we import the function and then create a list of employee objects and then call “findEmployeesByRole” and “findEmployeesByLocation” methods on it.

Even though the methods findEmployeesByRole” and “findEmployeesByLocation” are not available on the List, it will call the “EmployeeFunction” class methods because of the implicit function.



import EmployeeFunction.employeeFunction

object EmployeeMain {

    def main(args: Array[String]): Unit = {

        val employees = List(Employee(name = "name0", age = 34, role = "programmer", location = "USA"),
                             Employee(name = "name1", age = 34, role = "manager", location = "USA"),
                             Employee(name = "name2", age = 34, role = "analyst", location = "USA"),
                             Employee(name = "name3", age = 33, role = "manager", location = "Canada"),
                             Employee(name = "name4", age = 34, role = "tech lead", location = "India"),
                             Employee(name = "name5", age = 37, role = "manager", location = "India"))

        println("All USA employees are\n" + employees.findEmployeesByLocation("USA"))
        println("All managers are:\n"+employees.findEmployeesByRole("manager"))

    }

}


Refer below the output of the above program



All USA employees are
List(Employee(name0,34,programmer,USA), Employee(name1,34,manager,USA), Employee(name2,34,analyst,USA))
All managers are:
List(Employee(name1,34,manager,USA), Employee(name3,33,manager,Canada), Employee(name5,37,manager,India))


Advertisements

Scala Try

The Try type in scala represents a computation that may either result in an exception, or return a successfully computed value.

In this post, We see how we can use Try type with an example.

Assume that we have a list of string and want to convert each value into number and If the value is not valid, then we have to throw an exception. We also do not want to break the program when an exception has been thrown.

Refer the below example to know how we can do that with Try type.



import scala.util.{Failure, Try}

object ScalaTryCatchExample {

    def main(args: Array[String]): Unit = {

        val values = List("1", "2", "3", "test", "5")

        values.foreach(value => {

            val tryOption = Try(convertValuesAsNumber(value))
            tryOption match {
                case Failure(e) =>
                    println(s" $value is not valid number. Exception is $e")
                case _ =>
            }
            println("Number:" + tryOption.toOption)
        }
        )

    }

    def convertValuesAsNumber(value: String): Integer = {
        if (value == null || !value.matches("[0-9]")) {
            throw new IllegalArgumentException()
        }
        Integer.valueOf(value)
    }
}


In the above Scala Object, we have “convertValuesAsNumber” method which is used to convert a string value into a number and also it throws an exception when if the value is null and not a valid number.

Here we wrap the convertValuesAsNumber method call into Try type. So when an exception throws, it would not break the program immediately. Instead the failure object is returned. So we can use match to find out this and finally call toOption method to get the value. If any exception throws then it will return a ‘None’ option.

We can also re-write the above program like below,


import scala.util.{Failure, Try}

object ScalaTryCatchExample {

    def main(args: Array[String]): Unit = {

        val values = List("1", "2", "3", "test", "5")

        values.foreach(value => {

            val tryOption = Try(Integer.valueOf(value))
            tryOption match {
                case Failure(e) =>
                    println(s" $value is not valid number. Exception is $e")
                case _ =>
            }
            println("Number:" + tryOption.toOption)
        }
        )

    }
}


The output of the above example is given below


Number:Some(1)
Number:Some(2)
Number:Some(3)
 test is not valid number. Exception is java.lang.IllegalArgumentException
Number:None
Number:Some(5)

How to use scopt(https://github.com/scopt/scopt)

In this post, we are going to see how we can use scopt which is a scala library
used to parse the command line options.

The github URL is https://github.com/scopt/scopt

Lot of time, We may need to read and parse the command line arguments. So this simple command line parser used to reduce our burden. Let see how we can use this with a simple example.

Assume that you want to read two parameters from command line, they are input and output directory respectively. You want to throw an error if those parameters are not available.



package com

object ScalaApp extends App {

    case class Arguments(inputDir: String = "",
                         outputDir: String = "")

    val parser = new scopt.OptionParser[Arguments]("Parsing application") {

        opt[String]('i', "inputDir").
            required().valueName("").action((value, arguments) => arguments.copy(inputDir = value))

        opt[String]('o', "outputDir").
            required().valueName("").action((value, arguments) => arguments.copy(outputDir = value))

    }

    def run(arguments: Arguments): Unit = {
        println("Input Dir:" + arguments.inputDir)
        println("Output Dir:" + arguments.outputDir)
    }

    parser.parse(args, Arguments()) match {
        case Some(arguments) => run(arguments)
        case None =>
    }

}


In the above example, I have created a case class Arguments has two fields, input and output directory and I parse the input arguments, if the value is available, then I assign the value to the corresponding field in the case class.

When i run the program with the below command line arguments, then the output will look below,

-i /home/bala/input -o /home/bala/output


com.ScalaApp -i /home/bala/input -o /home/bala/output
Input Dir:/home/bala/input
Output Dir:/home/bala/output

When i run the program without any command line arguments, then it will show the below error as i specified those arguments as required arguments.



com.ScalaApp

Error: Missing option --inputDir
Error: Missing option --outputDir
Usage: test [options]

  -i, --inputDir    
  -o, --outputDir   


Scala Partial Function

A partial function is a function that is valid for only a subset of values of those types you might pass in to it.

Partial function can be defined by using ‘case’ statement.

Let us define a partial function and to know how to use it.


  val multiplyBy100: PartialFunction[Int, Int] = {
    case x if x > 0 => x * 100
  }

The above partial function gets an integer value as input and process it and returns another integer value. Here, we check the value is negative or not before applying multiple operation.

Consider that we have a list of numbers and want to multiply each value by value 100, then we can make use of the above function.

Partial functions can help us to get rid of any side effects for example avoiding the negative number in list.

Refer the below complete code and its output.



object ScalaExample {

  //Partial function: MUltiply the input by 100 and return it.
  val multiplyBy100: PartialFunction[Int, Int] = {
    case x if x > 0 => x * 100
  }

  def main(args: Array[String]): Unit = {

    //List of numbers
    val numbers1 = List(1, 4, 5, 6, 7)
    //Use the partial function and coll
    println("numbers1::" + (numbers1 collect multiplyBy100))

    //List contains negative numbers as well
    val numbers2 = List(-1, -2, -3, 10)
    println("numbers2::" + (numbers2 collect multiplyBy100))

  }
}



numbers1::List(100, 400, 500, 600, 700)
numbers2::List(1000)


Scala’s PartialFunction trait contains the isDefinedAt method which can be called to check whether it handles the given value.

For example, We can call like this multiplyBy100.isDefinedAt(-1) which returns false. whereas this one multiplyBy100.isDefinedAt(1) returns true.

Scala Companion Object

A companion object in scala is an object that’s declared in the same file as a class and has the same name as class. So we can create an instance of class without new keyword.

In this post, we are going to see how we can use Scala companion object with an example.

Refer the below code, we define the case class Book and the corresponding companion object with two apply methods to provide multiple constructors for “Book” case class and the “apply” methods provide default values for the unavailable fields.

Refer the main method of MainScala object where we create an instance Book class without new keyword and the companion object apply method would be called by that time.



object MainScala {

  def main(args: Array[String]) = {

    val book1 = Book("title1", 100.0f, "author1")
    val book2 = Book("title2", 50.0f)
    println("book1: " + book1)
    println("book2: " + book2)
  }
}

case class Book(title: String, price: Float, author: String, publisher: String)

object Book {

  def apply(title: String, price: Float, author: String): Book = {

    val book = new Book(title, price, author, "")
    book
  }

  def apply(title: String, price: Float): Book = {

    val book = new Book(title, price, "", "")
    book
  }
}


The output of the above example is given below


book1: Book(title1,100.0,author1,)
book2: Book(title2,50.0,,)

Scala – sort/sortWith/sortBy functions

In this post, we are going to see how we can use scala sort related function with examples.

Assume that we have a list of fruits and we want to sort the fruit name in different order.

Refer the below code to know how to do that.



object SortExample {


  def main(args: Array[String]): Unit = {

    val fruits = List("Water Melon", "Banana", "Carrot", "Apple", "Plums", "Orange")

    //To sort a list by ascending order
    println(fruits.sorted)

    //To sort a list by descending order
    println(fruits.sorted.reverse)

    //To sort a list by length
    println(fruits.sortWith(_.length > _.length))

    //To sort a list by length(descending)
    println(fruits.sortWith(_.length < _.length))

  }
}

The output of the above code is given below,


List(Apple, Banana, Carrot, Orange, Plums, Water Melon)
List(Water Melon, Plums, Orange, Carrot, Banana, Apple)
List(Water Melon, Banana, Carrot, Orange, Apple, Plums)
List(Apple, Plums, Banana, Carrot, Orange, Water Melon)

Now, We will see how we can use sortBy function to sort a list.

The definition of the sortBy function is given below,



def sortBy[B](f: (A) ⇒ B)(implicit ord: math.Ordering[B]): List[A]
Sorts this Seq according to the Ordering which results from transforming an implicitly given Ordering with a transformation function.


Refer the below code, where we use sortBy function to sort the employee objects list in three different ways.


object SortByExample {

  case class Employee(name: String,
                      age: Int,
                      designation: String,
                      salary: Int)

  def main(args: Array[String]): Unit = {

    val employees = List(Employee("Bala", 31, "Developer", 500000),
      Employee("John", 33, "Tester", 200000),
      Employee("Bob", 35, "Tech Lead", 300000),
      Employee("Woods", 30, "Manager", 400000),
      Employee("Robert", 30, "Tester", 200000),
      Employee("Jon", 30, "Tester", 100000),
      Employee("Paul", 26, "Sales Person", 100000),
      Employee("Jason", 25, "Sales Executive", 100000),
      Employee("Jill", 25, "Sales Executive", 200000),
      Employee("Steve", 27, "Product Owner", 500000))

    employees
      .sortBy(_.age)
      .foreach(println(_))

    employees
      .sortBy(x => (x.salary, x.age))
      .foreach(println(_))

    val orderForDesignation = Map("Product Owner" -> 0, "Manager" -> 1, "Tech Lead" -> 2, "Developer" -> 3, "Tester" -> 4)

    employees
      .sortBy(x => (orderForDesignation.get(x.designation).orElse(Some(10)), x.name))
     .foreach(println(_))

  }

}

We have Employee case class and it contains name, salary, designation and age fields and we create a list with different details, then we call sortBy function and pass the age field to sort the list by age.

The output looks like below,


Employee(Jason,25,Sales Executive,100000)
Employee(Jill,25,Sales Executive,200000)
Employee(Paul,26,Sales Person,100000)
Employee(Steve,27,Product Owner,500000)
Employee(Woods,30,Manager,400000)
Employee(Robert,30,Tester,200000)
Employee(Jon,30,Tester,100000)
Employee(Bala,31,Developer,500000)
Employee(John,33,Tester,200000)
Employee(Bob,35,Tech Lead,300000)

Now we want to sort the list by salary and then age. To do that we have to pass the salary and age fields to sortBy function in the right order.
The output looks like below,


Employee(Jason,25,Sales Executive,100000)
Employee(Paul,26,Sales Person,100000)
Employee(Jon,30,Tester,100000)
Employee(Jill,25,Sales Executive,200000)
Employee(Robert,30,Tester,200000)
Employee(John,33,Tester,200000)
Employee(Bob,35,Tech Lead,300000)
Employee(Woods,30,Manager,400000)
Employee(Steve,27,Product Owner,500000)
Employee(Bala,31,Developer,500000)


Now, we want to sort it by designation but follow a different order. The order should be like this “Product Owner -> Manager -> Tech Lead -> Developer -> Tester.

To do that we have to maintain a Map contains designation to order mapping and this Map to be used in sortBy function and we also use name as secondary sorting.

The output looks like below,


Employee(Steve,27,Product Owner,500000)
Employee(Woods,30,Manager,400000)
Employee(Bob,35,Tech Lead,300000)
Employee(Bala,31,Developer,500000)
Employee(John,33,Tester,200000)
Employee(Jon,30,Tester,100000)
Employee(Robert,30,Tester,200000)
Employee(Jason,25,Sales Executive,100000)
Employee(Jill,25,Sales Executive,200000)
Employee(Paul,26,Sales Person,100000)


Scala – Currying function

A Currying function is a function which has multiple parameter list but can be called with few arguments and yields another function which accepts the missing parameters as its arguments.

Consider that we have a list names and want to add prefix and suffix to each name. Let’s see how we can do this with a curried function.

Scala-Currying

In the above example, the function “addPrefixSuffix” is a curried function which accepts three arguments such as prefix, suffix and name. So in the “main” function, I pass only two arguments to this so it will yield another function to accept the missing parameter(name).