Monday 25 December 2017

Introduction to Scala - X

For all the work in this post, we will use Read-Evaluate-Print-Loop Scala interpreter. Some familiarity with Java will be of great help in understanding Scala. In this post, we will focus on parameters passed to methods and values returned from methods.

Methods can return multiple values in the form of tuples. In simple language, tuples can be thought of as a group of items separated by a comma. An example is shown below:

(1,2,3)

The example shown below returns the integer passed to it and classifies it as even or odd:

def EvenOdd(i:Int) = {
  if (i % 2 == 0)
    (i, " is even")
  else
    (i, " is odd")
}


We can test with below code where tuples are returned:

println(EvenOdd(101))

println(EvenOdd(100))

The results are shown below:

scala> def EvenOdd(i:Int) = {
     |   if (i % 2 == 0)
     |     (i, " is even")
     |   else
     |     (i, " is odd")
     | }
EvenOdd: (i: Int)(Int, String)

scala> println(EvenOdd(101))
(101, is odd)

scala> println(EvenOdd(100))
(100, is even) 


During a method call, we can set the arguments based on the name of the parameters in the order that we want. An example is shown below:

def PersonName(Title:String, FirstName: String, LastName: String) = {
  s"The name is $Title. $FirstName $LastName"
}

PersonName("Mr","John","Doe")


The results are shown below:

scala> def PersonName(Title:String, FirstName: String, LastName: String) = {
     |   s"The name is $Title. $FirstName $LastName"
     | }
PersonName: (Title: String, FirstName: String, LastName: String)String

scala> PersonName("Mr","John","Doe")
res86: String = The name is Mr. John Doe


Notice the way the string is returned. Parameters as Title, FirstName, LastName can be referenced using $.

The order of the parameters can be rearranged as shown below:

PersonName(FirstName="John",Title="Mr",LastName="Doe")

The results are shown below:

scala> PersonName(FirstName="John",Title="Mr",LastName="Doe")
res87: String = The name is Mr. John Doe


It is only natural that if we pass unnamed arguments as in the earlier case, then, they should be in the same order as they appear in the method definition, else, we get an error like the example below:

PersonName("John",Title="Mr",LastName="Doe")

The results are shown below:

scala> PersonName("John",Title="Mr",LastName="Doe")
<console>:13: error: parameter 'Title' is already specified at parameter position 1
       PersonName("John",Title="Mr",LastName="Doe")


We can also set default values to the parameters. In the below example, Title has a default value "Mr":

def PersonName1(Title:String = "Mr", FirstName: String, LastName: String) = {
  s"The name is $Title. $FirstName $LastName"
}


PersonName1(FirstName="John",LastName="Doe")

The results are shown below:

scala> def PersonName1(Title:String = "Mr", FirstName: String, LastName: String) = {
     |   s"The name is $Title. $FirstName $LastName"
     | }
PersonName1: (Title: String, FirstName: String, LastName: String)String

scala> PersonName1(FirstName="John",LastName="Doe")
res92: String = The name is Mr. John Doe


The last topic we see is that of By-Name Parameters. The By-Name parameters are evaluated every time they are used in the function body. They are defined by using => prefix before the type and after the : symbol. By contrast, the normal parameter of By-Value parameter is evaluate once when the function call is made. An example is shown below:

def Calculation(Condition1: => Boolean)(Condition2: => Unit): Unit = {
  if (Condition1) {
    Condition2
  }
}


To test it, we use below code:

val i = -5
Calculation(i>0){
println(scala.math.sqrt(i))
}


val i = 5
Calculation(i>0){
println(scala.math.sqrt(i))
}


The results are shown below:

scala> def Calculation(Condition1: => Boolean)(Condition2: => Unit): Unit = {
     |   if (Condition1) {
     |     Condition2
     |   }
     | }
Calculation: (Condition1: => Boolean)(Condition2: => Unit)Unit

scala> val i = -5
i: Int = -5

scala> Calculation(i>0){
     | println(scala.math.sqrt(i))
     | }

scala> val i = 5
i: Int = 5

scala> Calculation(i>0){
     | println(scala.math.sqrt(i))
     | }
2.23606797749979


It is instructive to note that:

Condition1 = (i>0)
Condition2 =  println(scala.math.sqrt(i))

When i = -5, (i>0) evaluates to false. So, the println command is not executed. In the second case when i = 5, (i>0) evaluates to true. So, the println command is executed.

This concludes the discussion on methods.