Professional Documents
Culture Documents
Scala
Scala
Implicits
Implicits is an interesting feature which simplifies your code by leaving out obvious
details which the compiler can automatically infer. There are two ways to use
implicits:
• An implicit parameter is a parameter to a method which doesn't have to be
passed explicitly. The value of the parameter is inferred by the Scala compiler based
on its type and the implicit values in scope.
• An implicit conversion is a function that converts one type to another. This
function is called by the Scala compiler when a type conversion is required.
Implicit parameters
Following is a method find defined with an implicit parameter x. The
keyword implicit is used to mark an implicit parameter.
`def find(implicit x : Int) = x
`
You can call this method like any other method by passing an integer value for the
parameter x.
find(10) will return value 10.
Now you can call the same method without passing any parameter, if you have an
implicit integer value defined in scope as given below.
The scala compiler passes the implicit integer value test to the find method when you
call it without any parameter. So you get 5 as the function return value.
def multiply(x:Int)(implicit y:Int=5) = x*y
class CustomString(val s: String) {
def isNumeric = s forall Character.isDigit
}
implicit def StrToCustomString(s: String): CustomString = new CustomStr
ing(s)
// Avoid handling the test method.
def test(var1:String){
val output = var1.isNumeric
println(output)
Implicit conversions
In this example, the method find is similar to the previous example but without an
implicit parameter.
def find(x: Int) = x
type mismatch;
found : String("test")
required: Int
Implicit conversions
If you have an implicit function which converts String to Integer, you can make the
previous code work. You can create an implicit function as specified here:
implicit def strToInt(x : String) = x.length
Now your call find(“test”) will succeed and will return the length of the string “test”
find("test") //returns 4
object Result {
class CustomString(val s: String) {
// Define method with name findLength to get the length of the
string 's'
def findLength = s.length
}
class CustomInt(val number : Int){
//Define method with name multiply to perform multiplication of
the 'number' by 10
def multiply = 10*number
}
// Define your implicit functions here.
implicit def StrToCustomString(s:String):CustomString = new CustomS
tring(s)
implicit def StrToCustomInt(output2:String):CustomInt = new CustomI
nt(output2.toInt)
// Don't modify the test method.
def test(var1:String){
val o1 = var1.findLength
println(o1)
val output = var1.multiply
println(output)
}
For Comprehensions
Generally, a for-comprehension is of the form:
for (seq) yield expr
for {
n = p.name // a definition
} yield n
Also there can be multiple generators separated by semicolon as shown here:
yield (i, j)
For Comprehensions
Here are two simple for-comprehension examples which return two Lists.
yield i+10
// Output is List(11,12,13,14,15)
yield i
// Output is List(2,4)
For Comprehensions
For-expression corresponding to the equation given in the image is
yield x*x
def forComprehensions(var1: Int) {
// Put your code here
for (i <- 1 to var1) {
print(i)
}
println()
for(i <- 1 until var1){
print(i)
}
// Put your code here
}
}
Options
Suppose you have a method which returns a string value optionally, i.e.. this method
returns a valid string in most of the cases, but in some special cases, there is no string
value to return.
If you are working in other programming languages like Java, you would have
returned a null in such a case. But the client code, which calls your method, may not
be expecting null as the return value. If the null type is not handled in the client code
it will result in a NullPointerException.
In Scala, you don't return null values. Instead, you make it explicit to the client code
that the return value of your method is an optional string. This is done using
the Option[A] trait.
Option can be considered as a container which can hold values of any type. Such a
value can be of two forms: Some(x), where x is the actual value, or the None object,
which represents a missing value.
Following is a sample Scala method which returns a String value optionally. Note that
the return type is Option[String] instead of String.
Options examples
If you have to return Integer value optionally, the return type would
be Option[Integer]. The client code will call the find method and handle the return
value as shown.
if(result.isDefined){
else {
result match {
bject Result {
// Define your show function here
def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
}
object Solution {
def main(args: Array[String]) {
val capitals = Map("France" -> "Paris", "Japan" -> "Tokyo")
println("Capital of Japan : " + Result.show(capitals.get( "Japa
n")) )
println("Capital of India : " + Result.show(capitals.get( "Indi
a")) )
}
}
Currying
You can convert this to a curried function by simply separating the parameters into
multiple parameter lists.
This technique got its name from the American mathematician, Haskell Curry.
(
add(1)(2) //returns 3 :Int
def partialFunctionImplementation(input1: Int, input2: Int) {
def modNum(input1: Int)=(input2: Int) => input1 % input2
//Put your code here to create the partial function.
val customMod = modNum(input1)
val output = customMod(input2)
println(output)
}
object Solution {
def main(args: Array[String]) {
val input1 = StdIn.readLine.trim.toInt
val input2 = StdIn.readLine.trim.toInt
Result.partialFunctionImplementation(input1, input2)
}
}
Tail Recursion
A function which calls itself is known as a recursive function. A recursive function
becomes tail recursive when the recursive call is the last thing executed by the
function. The following function finds the factorial of a given number.
Tail Recursion
A modified version of the factorial function which is tail recursive is as follows:
def factorial(x: Int): Int = {
def iter(n: Int, acc: Int): Int =
if (n == 0) acc else iter(n-1, n * acc)
iter(x, 1)
}
@tailrec
def factorial(x: Int): Int = ...
Parallel Collections
The basic course on Scala covers the collection classes and the various operations
available. All the methods of a collection process its elements sequentially. Scala also
has got parallel collections which process the elements in parallel.
You can convert any existing sequential collection to a parallel collection using
the par method.
In this sample, the println method will be called for 10 elements, one after the other.
r.foreach(println)
Whereas with the parallel collection, the println method will be called for the
elements in parallel.
p.foreach(println)
def uniformLists(input1: Int) {
val unlist = List.fill(input1)("TCS")
println(unlist)
}
Actors
The Actor Model provides a high level of abstraction for writing concurrent and
distributed systems. The developer does not have to deal with explicit locking and
thread management when creating concurrent and parallel systems.
Actor is an object that receives messages and takes action on
those messages.
Creating Actors
To create an actor, extend the Actor trait provided by the Akka library and implement
the receive method. The following example creates a simple actor, called MyActor,
that prints a message to the console when it receives a string message:
import akka.actor.Actor
class MyActor extends Actor {
def receive = {
case "Hello" => println("received Hello")
case _ => println("received unknown message")
}
}
Actor System
Before sending any messages to MyActor, the actor needs to be instantiated by
creating an ActorSystem. The ActorSystem is like a manager of one or more actors. It
provides a method called actorOf that takes the configuration
object (akka.actor.Props) and, optionally, the name of the actor:
import akka.actor.Props
import akka.actor.ActorSystem
val system = ActorSystem("testing")
val a = system.actorOf(Props[MyActor])
a ! "Hello"
Thread.sleep(50)
system.shutdown()
Actor System
The actor system will create the infrastructure required for the actor to run.
Once this is done, system.shutdown() shuts down the infrastructure along with all its
actors.
We have added Thread.sleep in the previous example to give the actors some time
to process any unprocessed messages before the shutdown.
Replying to Messages
An Actor can reply to the sender of the message using the sender() method. This
method provides ActorRef of the actor that sent the last received message.
For example, the following code inside the receive method sends a message x, back
to the sender.
sender() ! x
This would only work if the original sender was also an Actor which has
a receive method. The second option of getting response is using Future.
Future
We use the “?” method (known as “ask”) to send a message. It sends a
message asynchronously and returns a Future representing a possible reply.
import akka.pattern.ask
import scala.concurrent.Await
import akka.util.Timeout
import scala.concurrent.duration._
implicit val timeout = Timeout(5 seconds)
val future = a ? "Hello"
val result = Await.result(future, 5 seconds).asInstanceOf[String]
println(result)
def forComprehensions(input1: Int) {
// Put your code here
val intList = List.range(1,input1+1)
for (i <- intList if i % 2 == 0)
println(i)
val stringList :List[String] = List("Scala", "Ruby", "Python",
"C#", "Java", "Groovy", "JavaScript", "PHP", "Haskell")
for (s<- stringList if (s startsWith "P"))
println(s)
//Put your code here
}
def factorial(x: Int): Int = {
@tailrec
def iter(n: Int, acc: Int): Int =
if (n == 0) acc else iter(n-1, n * acc)
iter(x, 1)
}
}
def implicitVariables(input1: Int) {
implicit val test = 5
val intList = List.range(1,input1+1)
def add(x : Int)(implicit y: Int) = x + y
for(i <- intList){
println(add(i))
}
}
}
def findEven(input1: Int) {
val numberList :List[Int]=(1 to input1).flatMap((x:Int)=>List(x)
).toList
def findevent (x:Int):Option[Boolean] =
{
if (x%2==0)
Some(true)
else
None
}
// Put your code here
for (n <- numberList) {
print(n)
findevent(n) match {
case Some(true) => println(" is even.")
case None => println(" is odd.")
}
}
}