Scala Quick Notes :: Part - 8
Bhaskar S | 02/28/2015 |
Overview
In this part of the series, we will look at using Higher-Order functions with Scala Collections, explore Scala Implicit arguments and conversions, and explore basic Scala Concurrency options.
Hands-on With Scala - VIII
The following is the Scala program named Sample26.scala:
Executing the program Sample26.scala results in the output:
list = List(5, 10, 15, 20, 25, 30) set = Set(Audi, Mercedes, Lexus, Jaguar, BMW, Acura) map = Map(MSFT -> 42, AAPL -> 128, ORCL -> 35, INTC -> 35, GOOG -> 560, CSCO -> 27) ls1 = List(10, 20, 30) st1 = Set(Audi, BMW) mp1 = Map(AAPL -> 128, GOOG -> 560) ls2 = List(10, 20, 30) st2 = Set(Audi, BMW) mp2 = Map(AAPL -> 128, GOOG -> 560) ls3 = List(1, 2, 3, 4, 5, 6) st3 = Set(5, 6, 3, 8, 4) mp3 = Map(MSFT -> 47, AAPL -> 133, ORCL -> 40, INTC -> 40, GOOG -> 565, CSCO -> 32) sum1 = 105 con1 = Audi, Mercedes, Lexus, Jaguar, BMW, Acura sum2 = 105 con2 = Audi, Mercedes, Lexus, Jaguar, BMW, Acura sum3 = 105 con3 = -> | Audi | Mercedes | Lexus | Jaguar | BMW | Acura
The following section explains some of the aspects of the Scala program Sample26.scala:
Scala collection traits Map, Seq, and Set derive from the Scale trait Iterable.
Scala trait Seq has LinearSeq as one of its sub-traits.
Scala class List derives from the trait LinearSeq
The filter method on a Scala collection returns all the elements of the collection for which the specified predicate function (function that returns a Boolean) returns a true
Ex: list.filter((a: Int) => a % 2 == 0)
The following is a shorter form of the above example:
Ex: list.filter(_ % 2 == 0)
The map method on a Scala collection returns a new collection by applying the specified function
Ex: list.map(_ / 5)
Ex: set.map(_.length)
Ex: map.map((a) => (a._1, a._2+5))
The reduce method on a Scala collection performs the specified operation on the first two elements of the collection to produce a result. Next, the operation is applied to the result and the third element from the collection to produce a new result. Next, the operation is applied to the new result and the fourth element from the collection to produce yet another result and so on till all the elements of the collection are exhausted
Ex: list.reduce((a: Int, b: Int) => a + b)
The following is a shorter form of the above example:
Ex: list.reduce(_ + _)
The fold method on a Scala collection performs the specified operation on the specified argument and the first element of the collection to produce a result. Next, the operation is applied to the result and the second element from the collection to produce a new result. Next, the operation is applied to the new result and the third element from the collection to produce yet another result and so on till all the elements of the collection are exhausted
Ex: list.fold(0)(_ + _)
The following is the Scala program named Sample27.scala:
Executing the program Sample27.scala results in the output:
DEBUG :: Welcome to Scala INFO :: Hello Scala Implicit !!! [1] int2Fraction(5) + 1/2 = 11/2 [2] 5 + 1/2 = 11/2
The following section explains some of the aspects of the Scala program Sample27.scala:
Scala allows one or more Curried method parameter(s) to implicitly assume values from the current namespace. This can be done using the implicit keyword.
In other words, when a Curried method parameter is prefixed with the keyword implicit and the method is invoked without specifying that parameter, Scala will use the value of any variable (of the same parameter type) defined using the implicit keyword from the current namespace
Ex: def logger(a: String)(implicit b: String) = printf(s"${b} :: ${a}\n") { implicit val level = "INFO"; logger("Hello Scala Implicit !!!") }
A Scala implicit function allows for automatic conversion of a data type from one type to another type. In our example, we are able to perform the + operation on a Scala Int and our custom Fraction class. Scala automatically invokes the conversion method int2Fraction on the Scala Int to convert it into a Fraction class
Ex: implicit def int2Fraction(a: Int) = new Fraction(a, 1); printf("[2] 5 + %s = %s\n", fr, 5 + fr)
The following is the Scala program named Sample28.scala:
Executing the program Sample28.scala results in the output:
pool-1-thread-2: Am thread two executing ... pool-1-thread-1: Am thread one executing ... Waiting for factorial 5 and 10 results ..... onSuccess:: Factorial of 5 = 120 onComplete:: Factorial of 10 = 3628800 Done with factorial 5 and 10 !!! Waiting for factorial 101 results ..... onFailure:: Exception for Factorial of 101 :: Stack Error Done with factorial 101 !!!
The following section explains some of the aspects of the Scala program Sample28.scala:
One can use the Java Thread class or the Java Runnable interface with the Java Executors to run one or more tasks concurrently
In the first part of our example, we demonstrate basic concurrency using Java Runnable with the Java Executors. Notice the use of implicit parameter
One can also use a Scala Future to execute one or more tasks concurrently. When a Future is created, it immediately starts to execute and returns a result at a later time via callbacks.
There are two ways to define the callbacks:
1. Define a Partial function named onComplete with two match cases Success (match on success) and Failure (match on failure)
2. Define explicit callbacks for success and failure. If the execution is successful, the callback is to a Partial function named onSuccess. If the execution is a failure, the callback is to a Partial function named onFailure
The import statement scala.concurrent.ExecutionContext.Implicits.global imports a default global execution namespace that defines a default thread pool using implicit values
References