Sunday 31 December 2017

Introduction to Scala - XVII

We continue the journey on Scala on the topic of  for comprehensions in this post. 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.

For comprehensions in Scala are an enhancement over the conventional for loops in other languages. We have already seen three forms of for loop in this post. In the last few posts, we have covered many members of Collections. So, let us look at a simple for loop as shown below:

val Map1: Map[String,Int] = Map("King" -> 24000, "Kochhar" -> 17000, "De Haan" -> 17000, ("Hunold", 9000), ("Ernst", 6000), ("Austin", 4800))

var Map0: Map[String,Int] = Map()
for (m <- Map1) {
  if (m._1.head == 'K') {
    Map0 += ((m._1,m._2))
  }
}
println(Map0)


The results are shown below:

scala> val Map1: Map[String,Int] = Map("King" -> 24000, "Kochhar" -> 17000, "De Haan" -> 17000, ("Hunold", 9000), ("Ernst", 6000), ("Austin", 4800))
Map1: Map[String,Int] = Map(King -> 24000, Ernst -> 6000, Kochhar -> 17000, De Haan -> 17000, Austin -> 4800, Hunold -> 9000)

scala> var Map0: Map[String,Int] = Map()
Map0: Map[String,Int] = Map()

scala> for (m <- Map1) {
     |   if (m._1.head == 'K') {
     |     Map0 += ((m._1,m._2))
     |   }
     | }

scala> println(Map0)
Map(King -> 24000, Kochhar -> 17000)


The above code is quite straightforward. We define Map1 for our exercise. Map0 is a map with no elements. A simple for loop that filters the elements having employee names starting with 'K'. then, this printed out. In the next program, we add the if condition to the for clause:

for (m <- Map1 if m._1.head == 'K') {
    Map0 += ((m._1,m._2))
}
println(Map0)


The results are shown below:

scala> for (m <- Map1 if m._1.head == 'K') {
     |     Map0 += ((m._1,m._2))
     | }

scala> println(Map0)
Map(King -> 24000, Kochhar -> 17000)


The for program above is an example of the for comprehension that is a combination of for and if. It consists of :

1) a generator expression : m <- Map1, that generates the value for the intended for loop

2) a guard : if m._1.head == 'K', that filters the earlier defined values from generator expression

3) a definition: Map0 += ((m._1,m._2)), that is actually the processing part of the for loop

We can also have a yield added to complete the picture as shown below:

println(for (m <- Map1 if m._1.head == 'K') yield m)

The results are shown below:

scala> println(for (m <- Map1 if m._1.head == 'K') yield m)
Map(King -> 24000, Kochhar -> 17000)


Notice that above one line yields the same result as in previous two cases. Yield can be used for further processing and returning new collections as shown below:

print(for (m <- Map1 if m._1.head == 'K') yield {
val u = m
val numPattern = "[0-9]+".r
val matchPattern_List = numPattern.findAllIn(u.toString).toVector
matchPattern_List})


The results are shown below:

scala> print(for (m <- Map1 if m._1.head == 'K') yield {
     | val u = m
     | val numPattern = "[0-9]+".r
     | val matchPattern_List = numPattern.findAllIn(u.toString).toVector
     | matchPattern_List})
List(Vector(24000), Vector(17000))


Note that apart from the processing part in yield, we have brought in regular expressions. But, that is a topic for another day.

This concludes the discussion on for comprehension in Scala

Saturday 30 December 2017

Introduction to Scala - XVI

We continue the journey on Scala on the topic of Lists in this post. 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 look at how Lists are defined along with some features of Lists in Scala.

A List in Scala is a immutable set of ordered elements.

Ways to create a list:

1) An empty list holding integer elements 

val List0: List[Int] = List()

The results are shown below:

scala> val List0: List[Int] = List()
List0: List[Int] = List()

scala> List0
res23: List[Int] = List()


2) A List with initialized values:

scala> val List1: List[Int] = List(1,2,3,4,5)
List1: List[Int] = List(1, 2, 3, 4, 5)


scala> val List2: List[Int] = List(5,6,7,8,9,10)
List2: List[Int] = List(5, 6, 7, 8, 9, 10)


3) Using :: as shown below:

 scala> val List3 = 1 :: 3 :: 5 :: 7 :: 9 :: List()
List3: List[Int] = List(1, 3, 5, 7, 9)

scala> List3
res28: List[Int] = List(1, 3, 5, 7, 9)


There are many operations that can be performed that are common with Arrays, Vectors, Sets and Maps. In this post, we will look at some operations.

1)  :+ : Adds an element to List

 scala> List0
res38: List[Int] = List()

scala> List0 :+ 1
res39: List[Int] = List(1)

scala> List0 :+ 1 :+ 2
res40: List[Int] = List(1, 2)

scala> List0 :+ 1 :+ 2 :+ 3
res41: List[Int] = List(1, 2, 3)


2) :: : Adds an element to beginning of list

scala> List1 :: 6
<console>:13: error: value :: is not a member of Int
       List1 :: 6
             ^

scala> 6 :: List1
res44: List[Int] = List(6, 1, 2, 3, 4, 5)

scala> List1.::(6)
res45: List[Int] = List(6, 1, 2, 3, 4, 5)


3) ::: : Appends a given list

scala> List1
res51: List[Int] = List(1, 2, 3, 4, 5)

scala> List2
res52: List[Int] = List(5, 6, 7, 8, 9, 10)

scala> List1 ::: List2
res53: List[Int] = List(1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10)


4) combinations : Returns a iterator for various combinations of elements. Very similar to valuesIterator in Maps

scala> val List1_Iterator1 = List1.combinations(4)
List1_Iterator1: Iterator[List[Int]] = non-empty iterator

scala> while (List1_Iterator1.hasNext) {
     |   println(List1_Iterator1.next())
     | }
List(1, 2, 3, 4)
List(1, 2, 3, 5)
List(1, 2, 4, 5)
List(1, 3, 4, 5)
List(2, 3, 4, 5)


5) corresponds : Returns a boolean based on conditional comparison of two lists

scala> val List1: List[Int] = List(1,2,3,4,5)
List1: List[Int] = List(1, 2, 3, 4, 5)

scala> val List4: List[Int] = List(6,7,8,9,10)
List4: List[Int] = List(6, 7, 8, 9, 10)

scala> List1.corresponds(List4)((x,y) => (x+1) == y)
res63: Boolean = false

scala> List1.corresponds(List4)((x,y) => (x+5) == y)
res64: Boolean = true


6) dropWhile : Returns the longest predicate that satisfies a condition

scala> List1
res76: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.dropWhile(_ < 4)
res77: List[Int] = List(4, 5)


7) endsWith : Returns a boolean based on if the list matches end elements of a comparison list

scala> List1
res79: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.endsWith(List(4,5))
res80: Boolean = true


8) flatMap : Returns a List after applying a function

scala> List1
res103: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.flatMap(x => List(x*x))
res104: List[Int] = List(1, 4, 9, 16, 25) 


9) foreach : Returns a List after applying a function

scala> List1
res109: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.foreach(x=>println(x*x))
1
4
9
16
25


10)  isDefinedAt: Returns boolean if that index is valid

scala> List1
res113: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.isDefinedAt(3)
res114: Boolean = true

scala> List1.isDefinedAt(6)
res115: Boolean = false

  
11) map : Returns a List after applying a function

scala> List1
res116: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.map(x => x*x)
res117: List[Int] = List(1, 4, 9, 16, 25)


12)  maxBy : Returns element that will return maximum value when a function is applied

scala> List1
res119: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.maxBy(x => x*x)
res120: Int = 5


13)  permutations : Returns different permutations

scala> val List1_Iterator1 = List(1,2,3).permutations
List1_Iterator1: Iterator[List[Int]] = non-empty iterator

scala> while (List1_Iterator1.hasNext) {
     |   println(List1_Iterator1.next())
     | }
List(1, 2, 3)
List(1, 3, 2)
List(2, 1, 3)
List(2, 3, 1)
List(3, 1, 2)
List(3, 2, 1)


14) prefixLength : Returns length of largest predicate that satisfies a condition

scala> List1.prefixLength(_ < 3)
res124: Int = 2


15) reduce : Returns result after reduction of elements using a associative binary operator

scala> List1
res126: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.reduce((x,y) => x+y)
res127: Int = 15


16) reverseMap : Map in reverse order

scala> List1
res128: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.reverseMap(x=>x*x)
res129: List[Int] = List(25, 16, 9, 4, 1)


17) reverse_::: : Returns a reverse of list followed by second operand list

scala> List1
res130: List[Int] = List(1, 2, 3, 4, 5)

scala> List2
res131: List[Int] = List(5, 6, 7, 8, 9, 10)

scala> List1 reverse_::: List2
res132: List[Int] = List(5, 4, 3, 2, 1, 5, 6, 7, 8, 9, 10)


18) sameElements : Returns boolean if the elements in second list is same as that in first list

scala> List1
res134: List[Int] = List(1, 2, 3, 4, 5)

scala> List1 sameElements List1
res135: Boolean = true


19) segmentLength: Returns length of longest segment that satisfies a condition starting at an element

scala> List1
res137: List[Int] = List(1, 2, 3, 4, 5)

scala> List1 segmentLength (x => (x>=1 & x <=4), 0)
res138: Int = 4


20) size : Returns length of list

scala> List1
res141: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.size
res142: Int = 5


21) toString : Returns a string

scala> List1
res149: List[Int] = List(1, 2, 3, 4, 5)

scala> List1.toString
res150: String = List(1, 2, 3, 4, 5)


This concludes the discussion of Lists in Scala

 

Friday 29 December 2017

Introduction to Scala - XV

We continue the journey on Scala on the topic of Maps in this post. 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 look at how Maps are defined along with some features of Maps in Scala.

Map is a collection that has elements in the form of a pair of sub elements: one is a key and the other is a value. Keys have to be unique while values need not.

We can define maps as shown below:

1) An empty map that has a keys of type String and values of type Int:

val Map0: Map[String,Int] = Map()

The results are shown below:

scala> val Map0: Map[String,Int] = Map()
Map0: Map[String,Int] = Map()


2) A Map initialized with key, value pairs:

val Map1: Map[String,Int] = Map("King" -> 24000, "Kochhar" -> 17000, "De Haan" -> 17000)

The results are shown below:

scala> val Map1: Map[String,Int] = Map("King" -> 24000, "Kochhar" -> 17000, "De Haan" -> 17000)
Map1: Map[String,Int] = Map(King -> 24000, Kochhar -> 17000, De Haan -> 17000)


In the above case, to show the association between employee name and the corresponding salary, an arrow symbol, -> is used. Another way to create a Map is shown where name and salary and together in parentheses. We are using an mix of both below:

val Map2: Map[String,Int] = Map(("De Haan" -> 17000),("Hunold", 9000), ("Ernst", 6000), ("Austin", 4800))

The results are shown below:

scala> val Map2: Map[String,Int] = Map(("De Haan" -> 17000),("Hunold", 9000), ("Ernst", 6000), ("Austin", 4800))
Map2: Map[String,Int] = Map(De Haan -> 17000, Hunold -> 9000, Ernst -> 6000, Austin -> 4800)


Thus, we have created two maps. Like Sets, there are the mutable and immutable Maps.

There are many operations that can be performed that are common with Arrays, Vectors and Sets. In this post, we will look at some operations.

1) + : Adds one or more key, value pairs

scala> Map1
res81: Map[String,Int] = Map(King -> 24000, Kochhar -> 17000, De Haan -> 17000)

scala> Map1 + (("AddKey" -> 100))
res82: scala.collection.immutable.Map[String,Int] = Map(King -> 24000, Kochhar -> 17000, De Haan -> 17000, AddKey -> 100)

scala> Map1
res83: Map[String,Int] = Map(King -> 24000, Kochhar -> 17000, De Haan -> 17000)


scala> Map1 + (("AddKey" -> 100),("AddMoreKey",1000))
res84: scala.collection.immutable.Map[String,Int] = Map(King -> 24000, AddMoreKey -> 1000, Kochhar -> 17000, De Haan -> 17000, AddKey -> 100)

scala> Map1
res85: Map[String,Int] = Map(King -> 24000, Kochhar -> 17000, De Haan -> 17000)


2) ++ : Adds two maps

scala> Map1 ++ Map2
res86: scala.collection.immutable.Map[String,Int] = Map(King -> 24000, Ernst -> 6000, Kochhar -> 17000, De Haan -> 17000, Austin -> 4800, Hunold -> 9000)


3) - : Removes a key value when a key is passed

scala> Map1 - ("King")
res91: scala.collection.immutable.Map[String,Int] = Map(Kochhar -> 17000, De Haan -> 17000) 


4) apply : Returns value associated with a key

scala> Map1 apply ("King")
res93: Int = 24000


5) filter: filters based on both key and value criteria 

scala> Map1.filter((test:(String,Int)) => (test._1).startsWith("De"))
res114: scala.collection.immutable.Map[String,Int] = Map(De Haan -> 17000)


scala> Map1.filter((test:(String,Int)) => test._2 >=19000)
res118: scala.collection.immutable.Map[String,Int] = Map(King -> 24000)


scala> Map1.filter((test:(String,Int)) => (test._1).startsWith("Ki") & test._2 >=19000)
res119: scala.collection.immutable.Map[String,Int] = Map(King -> 24000)


6) filterKeys : filters based on key

scala> Map1.filterKeys(_.startsWith("De"))
res96: scala.collection.immutable.Map[String,Int] = Map(De Haan -> 17000)


7) getOrElse : Based on key, gets a value or sets a default if no corresponding key

scala> Map1.getOrElse("King",100000)
res129: Int = 24000

scala> Map1.getOrElse("Queen",100000)
res130: Int = 100000


8) isDefinedAt : Returns a boolean based on presence of a key

scala> Map1.isDefinedAt("King")
res131: Boolean = true


9) keySet: Returns a Set of all keys

scala> Map1.keySet
res132: scala.collection.immutable.Set[String] = Set(King, Kochhar, De Haan)


10) keys : Returns all keys

scala> Map1.keys
res133: Iterable[String] = Set(King, Kochhar, De Haan)


11) keysIterator : Returns an iterator for keys

scala> val Map1_keysIterator1 = Map1.keysIterator
Map1_keysIterator1: Iterator[String] = non-empty iterator

scala> while (Map1_keysIterator1.hasNext) {
     | println(Map1_keysIterator1.next())
     | }
King
Kochhar
De Haan


12)  mapValues: Applies a function on values. We are halving the value as shown below:

scala> Map1.mapValues(n => n/2)
res21: scala.collection.immutable.Map[String,Int] = Map(King -> 12000, Kochhar -> 8500, De Haan -> 8500)


13) sliding: Returns maps in sequence based on sliding window

scala> val Map1_sliding1 = Map1.sliding(2)
Map1_sliding1: Iterator[scala.collection.immutable.Map[String,Int]] = non-empty iterator

scala> while (Map1_sliding1.hasNext) {
     | println(Map1_sliding1.next())
     | }
Map(King -> 24000, Kochhar -> 17000)
Map(Kochhar -> 17000, De Haan -> 17000)


14)  valuesIterator: Similar to keysIterator but based on values

scala> val Map1_valuesIterator1 = Map1.valuesIterator
Map1_valuesIterator1: Iterator[Int] = non-empty iterator

scala> while (Map1_valuesIterator1.hasNext) {
     | println(Map1_valuesIterator1.next())
     | }
24000
17000
17000


15)  zipAll : Combines two maps with corresponding key, value pairs. If any pairs fall short, then, these are picked up from the next default values

scala> Map1
res13: Map[String,Int] = Map(King -> 24000, Kochhar -> 17000, De Haan -> 17000)

scala> Map2
res14: Map[String,Int] = Map(De Haan -> 17000, Hunold -> 9000, Ernst -> 6000, Austin -> 4800)

scala> Map1.zipAll(Map2,("test1",100),("test2",1000))
res15: scala.collection.immutable.Map[(String, Int),(String, Int)] = Map((King,24000) -> (De Haan,17000), (Kochhar,17000) -> (Hunold,9000), (De Haan,17000) -> (Ernst,6000), (test1,100) -> (Austin,4800))

 
In the above case, Map1 has fewer key, value pairs than Map2. So, the default value is set in last case

This concludes the discussion of Maps in Scala

Introduction to Scala - XIV

We continue the journey on Scala on the topic of Sets in this post. 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 look at how Sets are defined along with some features of Sets in Scala.

Sets are the same in Scala as in other languages: It does not contain duplicates.

We define a couple of Sets below and, then, use them in different operations. We can create Sets as follows:

1) An empty Set:

val Set0: Set[Int] = Set()
Set0

The results are shown below:

scala> val Set0: Set[Int] = Set()
Set0: Set[Int] = Set()

scala> Set0
res9: Set[Int] = Set()


2) A Set initialized with values:

var Set1 = Set(1, 1, 2, 3, 4, 5)
var Set2 = Set(5, 6, 7, 8, 9, 10, 10)


The results are shown below:

scala> var Set1 = Set(1, 1, 2, 3, 4, 5)
Set1: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> var Set2 = Set(5, 6, 7, 8, 9, 10, 10)
Set2: scala.collection.immutable.Set[Int] = Set(5, 10, 6, 9, 7, 8)


For the sake of technicality, the above sets are immutable. They cannot be modified in place. On the other hand, a mutable Set can be modified. Mutable Sets are created as follows:

scala> var MutableSet1 = collection.mutable.Set(1,2,3,4,5)
MutableSet1: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 4)


Different operations can be performed on Sets. Many of them are similar to those described on Arrays and Vectors. We will describe some of the operations below:

1)  & : Returns elements that are common

scala> Set1 & Set2
res14: scala.collection.immutable.Set[Int] = Set(5)


2)  &~ : Returns elements in first set not present in second set

scala> Set1 &~ Set2
res15: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)


3)  + : Can add one or multiple arguments based on parameters to a Set but ensures that the final Set has no duplicates

scala> Set1
res19: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> Set1 + 0
res20: scala.collection.immutable.Set[Int] = Set(0, 5, 1, 2, 3, 4)


scala> Set1 + (6,7,8)
res21: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 8, 4)


scala> Set1
res22: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)


4) - : Can remove an element or more elements depending on parameters

scala> Set1
res22: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> Set1 - 5
res23: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

scala> Set1 - (1,2,3,3,3)
res24: scala.collection.immutable.Set[Int] = Set(5, 4)

scala> Set1
res25: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)


5) -- : Returns elements from first Set after removing elements from second Set

scala> Set1 -- Set2
res38: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)


6) fold : Returns a result after folding the elements defined on an operation using a specified associative binary operator starting with an initial value as shown below:

scala> Set1
res49: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> Set1.fold (100) (_ + _)
res50: Int = 115

scala> (Set1 fold 100) (_ + _)
res51: Int = 115


7) groupBy: Partitions the set into maps based on a discriminator function

scala> Set1
res60: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> Set1 groupBy [Int] (_%2)
res61: scala.collection.immutable.Map[Int,scala.collection.immutable.Set[Int]] = Map(1 -> Set(5, 1, 3), 0 -> Set(2, 4))

8)  subsetOf : Returns boolean if set is a subset

scala> Set1
res63: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> Set(1,2) subsetOf Set1
res64: Boolean = true


9) toString : Returns a string

scala> Set1.toString
res66: String = Set(5, 1, 2, 3, 4)


10) union or | : Returns union of two sets

scala> Set1 union Set2
res75: scala.collection.immutable.Set[Int] = Set(5, 10, 1, 6, 9, 2, 7, 3, 8, 4)

scala> Set1 | Set2
res76: scala.collection.immutable.Set[Int] = Set(5, 10, 1, 6, 9, 2, 7, 3, 8, 4)


11) zip : Returns combined pairs as shown below:

scala> Set1
res68: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> Set2
res69: scala.collection.immutable.Set[Int] = Set(5, 10, 6, 9, 7, 8)

scala> Set1 zip Set2
res70: scala.collection.immutable.Set[(Int, Int)] = Set((3,9), (4,7), (1,10), (2,6), (5,5))


This concludes the discussion of Sets in Scala

Thursday 28 December 2017

Introduction to Scala - XIII

We continue with more Scala on the topic of Vectors in this post. 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 look at how Vectors are defined along with some features of Vectors in Scala.

After looking at Arrays in last post, we will see how Vector are useful in Scala programs. Vector is a immutable data structure that provides random access and updates in effectively constant time. It also facilitates very fast append and prepend.

Vectors can be defined as shown below:

i) An empty Vector:

val Vector0: Vector[Int] = Vector()

The results are shown below:

scala> val Vector0: Vector[Int] = Vector()
Vector0: Vector[Int] = Vector()

scala> Vector0
res7: Vector[Int] = Vector()


ii) A Vector initialized with values:

val Vector1 = Vector(1,1,2,3,4,5)
val Vector2 = Vector(5,6,7,8,9,10,10)

The results are shown below:

scala> val Vector1 = Vector(1,1,2,3,4,5)
Vector1: scala.collection.immutable.Vector[Int] = Vector(1, 1, 2, 3, 4, 5)


scala> val Vector2 = Vector(5,6,7,8,9,10,10)
Vector2: scala.collection.immutable.Vector[Int] = Vector(5,6, 7, 8, 9, 10, 10)


Most of the methods in Vector have the same behavior that we have seen in the case of Arrays here. We will see some of  methods that can be applied on Vectors:

1) :+ : An element is appended to vector

scala> Vector1 :+ 100
res3: scala.collection.immutable.Vector[Int] = Vector(1, 1, 2, 3, 4, 5, 100)


2)  +: : An element is prepended to array

scala> 100 +: Vector1
res4: scala.collection.immutable.Vector[Int] = Vector(100, 1, 1, 2, 3, 4, 5)


3)  addString : Takes a StringBuilder and returns a StringBuilder with all elements appended with a start, end and a separator

scala> Vector1 addString (b=new StringBuilder("Hello"),start=" Start ",sep=":",end=" End ")
res9: StringBuilder = Hello Start 1:1:2:3:4:5 End


4) aggregate : Aggregates results after application of  an operator to different elements

scala> Vector(1,1,2,3,4,5).aggregate(0)({ (sum, i) => sum + i }, { (p1, p2) => p1 + p2 })
res13: Int = 16


5) apply : Selects element by index

scala> Vector1 apply 1
res14: Int = 1


6)  diff : Returns difference between operands

scala> Vector1 diff Vector2
res24: scala.collection.immutable.Vector[Int] = Vector(1, 1, 2, 3, 4)


7) iterator :  Returns a Vector Iterator. This iterator can then be used to iterate over the different elements of the Vector

scala> val Vector1_Iterator = Vector1.iterator
Vector1_Iterator: scala.collection.immutable.VectorIterator[Int] = non-empty iterator

scala> while (Vector1_Iterator.hasNext) {
     |   println(Vector1_Iterator.next())
     | }
1
1
2
3
4
5


8) reverseIterator : Returns a Iterator with elements in reverse order

scala> while (Vector1_Reverse_Iterator.hasNext) {
     |   println(Vector1_Reverse_Iterator.next())
     | }
5
4
3
2
1
1


9) union : Returns union of operands

scala> Vector1 union Vector2
res29: scala.collection.immutable.Vector[Int] = Vector(1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10)


10) zipWithIndex: Zips the vector with its indices

scala> Vector1.zipWithIndex
res30: scala.collection.immutable.Vector[(Int, Int)] = Vector((1,0), (1,1), (2,2), (3,3), (4,4), (5,5))


This concludes the discussion of Vectors in Scala.

Wednesday 27 December 2017

Introduction to Scala - XII

We continue with more Scala on the topic of Arrays in this post. 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 look at how Arrays are defined along with some features of Arrays in Scala.

Three ways to define Arrays in Scala are:

i) With values of the elements that constitute the Array as shown below:

val ArrayWithInt = Array(1,2,3,4,5)

val ArrayWithAny = Array(1,2L,3.0F,4.0D,'5',"Hello")

The results are shown below:

scala> val ArrayWithInt = Array(1,2,3,4,5)
ArrayWithInt: Array[Int] = Array(1, 2, 3, 4, 5)

scala> val ArrayWithAny = Array(1,2L,3.0F,4.0D,'5',"Hello")
ArrayWithAny: Array[Any] = Array(1, 2, 3.0, 4.0, 5, Hello)


ii) define specifying the size as shown below:

var ArrayWithInt:Array[Int] = new Array[Int](5)

To see default values we can use below command:

ArrayWithInt

The results are shown below:

scala> var ArrayWithInt:Array[Int] = new Array[Int](5)
ArrayWithInt: Array[Int] = Array(0, 0, 0, 0, 0)

scala> ArrayWithInt
res155: Array[Int] = Array(0, 0, 0, 0, 0)


iii) Using ofDim command as below:

val ArrayWithInt = Array.ofDim[Int](5)

To see default values we can use below command:

ArrayWithInt

The results are shown below:

 scala> val ArrayWithInt = Array.ofDim[Int](5)
ArrayWithInt: Array[Int] = Array(0, 0, 0, 0, 0)

scala> ArrayWithInt
res210: Array[Int] = Array(0, 0, 0, 0, 0)


We can see that the array is initialized with 0s. To populate with values in this case and in earlier case, we can use below command:

for (i <- 0 to ArrayWithInt.length-1) ArrayWithInt(i) = i

ArrayWithInt

The results are shown below:

scala> for (i <- 0 to ArrayWithInt.length-1) ArrayWithInt(i) = i

scala> ArrayWithInt
res214: Array[Int] = Array(0, 1, 2, 3, 4)


Using ofDim, we can also create multidimensional arrays as shown below:

val MultiDimArrayWithInt = Array.ofDim[Int](5,6)

This creates a two dimensional array having five rows and six columns. The results are shown below:

scala> val MultiDimArrayWithInt = Array.ofDim[Int](5,6)
MultiDimArrayWithInt: Array[Array[Int]] = Array(Array(0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0)) 


Similarly, we can create a three dimensional array as shown below:

val MultiDimArrayWithInt = Array.ofDim[Int](3,3,3)

The results are shown below:

scala> val MultiDimArrayWithInt = Array.ofDim[Int](3,3,3)
MultiDimArrayWithInt: Array[Array[Array[Int]]] = Array(Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)), Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)), Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)))


To access individual elements of an array:

ArrayWithInt(0)

ArrayWithAny(5)

The results are shown below:

scala> ArrayWithInt(0)
res160: Int = 0

scala> ArrayWithAny(5)
res161: Any = Hello

To access with index number, we can use below code:


val ArrayWithAny = Array(1,2L,3.0F,4.0D,'5',"Hello") 

for(i <- 0 until ArrayWithAny.length){
  println(s"Element at index $i is " + ArrayWithAny(i))
}


The results are shown below:

scala> val ArrayWithAny = Array(1,2L,3.0F,4.0D,'5',"Hello")
ArrayWithAny: Array[Any] = Array(1, 2, 3.0, 4.0, 5, Hello)


scala> for(i <- 0 until ArrayWithAny.length){
     |   println(s"Element at index $i is " + ArrayWithAny(i))
     | }
Element at index 0 is 1
Element at index 1 is 2
Element at index 2 is 3.0
Element at index 3 is 4.0
Element at index 4 is 5
Element at index 5 is Hello


Next, we will see a series of methods that can be applied on Arrays and will be very useful when we work with Arrays. Let us define two arrays that we can use to showcase these methods as shown below:

scala> var a = Array(1,1,2,3,4,5)
a: Array[Int] = Array(1, 1, 2, 3, 4, 5)

scala> var b = Array(6,7,8,9,10,10)
b: Array[Int] = Array(6, 7, 8, 9, 10, 10)


1) ++  :  Appends second array to first array

scala> a.++(b)
res220: Array[Int] = Array(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10)


2) ++: : Appends first array to second array

scala> a.++:(b)
res221: Array[Int] = Array(6, 7, 8, 9, 10, 10, 1, 1, 2, 3, 4, 5)


3)  +: : An element is prepended to array

scala> a.+:(100)
res223: Array[Int] = Array(100, 1, 1, 2, 3, 4, 5)


4)  :+ : An element is appended to array

scala> a.:+(100)
res225: Array[Int] = Array(1, 1, 2, 3, 4, 5, 100)


5) addString : Takes a StringBuilder and returns a StringBuilder with all elements appended

scala> a.addString(new StringBuilder("Hello"))
res230: StringBuilder = Hello112345


6) addString : Another variant that takes a string separator

scala> a.addString(new StringBuilder("Hello"),":")
res231: StringBuilder = Hello1:1:2:3:4:5


7) contains : Checks if an element is there is array

scala> a.contains(1)
res235: Boolean = true


8) count : Counts elements that match a condition. In below case, it counts the number of 1s. _ signifies any element in Array

scala> a.count(_==1)
res242: Int = 2


9) distinct : Returns distinct elements

scala> a.distinct
res243: Array[Int] = Array(1, 2, 3, 4, 5)


10) drop : Drops first n elements

scala> a.drop(3)
res244: Array[Int] = Array(3, 4, 5)


11) dropRight : Drops last n elements

scala> a.dropRight(3)
res245: Array[Int] = Array(1, 1, 2)



12) dropWhile : Drops longest prefix that satisfies a condition

scala> a.dropWhile(_==1)
res249: Array[Int] = Array(2, 3, 4, 5)


13) exists : Returns boolean if condition is satisfied

scala> a.exists(_==1)
res250: Boolean = true


14) filter :  Filters elements that satisfy a condition

scala> a.filter(_%2==0)
res252: Array[Int] = Array(2, 4)


15) filterNot : Opposite of filter

scala> a.filterNot(_%2==0)
res253: Array[Int] = Array(1, 1, 3, 5)


16) find : Finds the first element that satisfies a condition

scala> a.find(_==2)
res254: Option[Int] = Some(2)



17) flatten : Flattens two dimensional arrays to one dimension

scala> val TwoDimArrayWithInt = Array(Array(1,2),Array(3,4))
TwoDimArrayWithInt: Array[Array[Int]] = Array(Array(1, 2), Array(3, 4))

scala> TwoDimArrayWithInt.flatten
res256: Array[Int] = Array(1, 2, 3, 4)



18) forall : Tests if  a condition satisfies all elements

scala> a.forall(_ %1==0)
res258: Boolean = true



19) foreach : Applies a function to all elements. We are borrowing the anonymous function from the first post.

scala> a.foreach( (x: Int) => println(x * x))
1
1
4
9
16
25


20) indexOf : Returns index of first occurrence of an element

scala> a.indexOf(3)
res273: Int = 3


21) init : Returns all elements except last

scala> a.init
res274: Array[Int] = Array(1, 1, 2, 3, 4)


22) last : Selects last element

scala> a.last
res277: Int = 5


23) length : Returns length of array

scala> a.length
res278: Int = 6


24) map : Applies a function to all elements of an array

scala> a.map(x => Math.sqrt(x))
res285: Array[Double] = Array(1.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.23606797749979)


25) max : Returns maximum in array

scala> a.max
res279: Int = 5


26) min : Returns minimum in array

scala> a.min
res280: Int = 1


27)  mkString : Returns a string of all elements

scala> a.mkString
res281: String = 112345


28)  mkString : Returns a string of all elements with a separator

scala> a.mkString(":")
res283: String = 1:1:2:3:4:5


29)  nonEmpty : Checks if Array is not empty

scala> a.nonEmpty
res286: Boolean = true


30) partition: Partitions based on a condition

scala> a.partition(_ %2==0)
res287: (Array[Int], Array[Int]) = (Array(2, 4),Array(1, 1, 3, 5))


31) product : Returns product of elements

scala> a.product
res288: Int = 120


31) reduce : reduces elements based on an operator as shown below:

scala> a.reduce( (x,y) => (x+y))
res284: Int = 16


32)  reverse : Reverses Array

scala> a.reverse
res289: Array[Int] = Array(5, 4, 3, 2, 1, 1)


33) slice : Slices the Array

scala> a.slice(1,3)
res290: Array[Int] = Array(1, 2) 


34)  sorted : Sorts Array

scala> a.sorted
res291: Array[Int] = Array(1, 1, 2, 3, 4, 5)


35) sum : Sum of elements in Array

scala> a.sum
res292: Int = 16


36) tail : Selects all elements except the first

scala> a.tail
res293: Array[Int] = Array(1, 2, 3, 4, 5)


37) take : Selects first n elements

scala> a.take(2)
res294: Array[Int] = Array(1, 1)


38) toList : Converts to List

scala> a.toList
res300: List[Int] = List(1, 1, 2, 3, 4, 5)


39) toSeq : Converts to Sequence

scala> a.toSeq
res302: Seq[Int] = WrappedArray(1, 1, 2, 3, 4, 5)


40) toVector : Converts to Vector

scala> a.toVector
res303: Vector[Int] = Vector(1, 1, 2, 3, 4, 5)


41) update : Updates the Array

scala> a.update(0,0)

scala> a
res296: Array[Int] = Array(0, 1, 2, 3, 4, 5)


This concludes the discussion of Arrays in Scala.

Tuesday 26 December 2017

Introduction to Scala - XI

We continue with more Scala on the topic of Pattern Matching in this post. 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 look at the different ways Pattern Matching can be implemented in Scala.

We already saw a brief example in an earlier post that is replicated below:

val x = 1
x match {
  case 1 => "One"
  case 2 => "Two" 
  case _ => "Unknown"
}

The results are shown below:


scala> val x = 1
x: Int = 1

scala> x match {
     |
     |   case 1 => "One"
     |
     |   case 2 => "Two"
     |
     |   case _ => "Unknown"
     | }
res104: String = One


We can also match on the basis of types as shown below:

def TypeMatch(input: Any) = input match {
  case i: Int => i.toBinaryString
  case d: Double => d.toInt
}

TypeMatch(-5)
TypeMatch(-5.9)


The results are shown below:

scala> def TypeMatch(input: Any) = input match {
     |   case i: Int => i.toBinaryString
     |   case d: Double => d.toInt
     | }
TypeMatch: (input: Any)Any

scala> TypeMatch(-5)
res105: Any = 11111111111111111111111111111011

scala> TypeMatch(-5.9)
res106: Any = -5


In the above example, the input is any object. If input is an integer, then, the input is converted into a binary string. If it is a Double, it is converted to an integer. Note that the case expressions, i and d are small case letters of the types that they describe.

Similar to above example, we can check for case classes as well as shown below:

case class Ferrari(Name: String, Type: String)
case class Ford(Name: String, Gas: String)

def CaseClassMatch(input: Any) = input match {
  case Ferrari(name, _) => s"Ferrari called $name"
  case Ford(name, gas) => s"Ford called $name, runs on $gas"
}


To test above code, we can use below code:

CaseClassMatch(Ferrari("California T","Automatic"))
CaseClassMatch(Ford("Endeavour","Diesel"))


The results are shown below:

 scala> case class Ferrari(Name: String, Type: String)
defined class Ferrari

scala> case class Ford(Name: String, Gas: String)
defined class Ford


 scala> def CaseClassMatch(input: Any) = input match {
     |   case Ferrari(name, _) => s"Ferrari called $name"
     |   case Ford(name, gas) => s"Ford called $name, runs on $gas"
     | }
CaseClassMatch: (input: Any)String


scala> CaseClassMatch(Ferrari("California T","Automatic"))
res120: String = Ferrari called California T

scala> CaseClassMatch(Ford("Endeavour","Diesel"))
res121: String = Ford called Endeavour, runs on Diesel


We can add a if clause to make this pattern matching more specific as shown in below program:

def CaseClassMatchWithIf(input: Any) = input match {
  case Ferrari(name, _) if (name == "California T") => s"Ferrari called $name"
  case Ford(name, gas) if (gas == "Petrol") => s"Ford called $name, runs on $gas"
}


Then, we can test the above code with below commands:

CaseClassMatchWithIf(Ferrari("CaliforniaT","Automatic")) 
CaseClassMatchWithIf(Ford("Endeavour","Petrol"))
CaseClassMatchWithIf(Ford("Endeavour","Diesel"))

The last command errors out as it fails the if test.

The results are shown below:

scala> def CaseClassMatchWithIf(input: Any) = input match {
     |   case Ferrari(name, _) if (name == "California T") => s"Ferrari called $name"
     |   case Ford(name, gas) if (gas == "Petrol") => s"Ford called $name, runs on $gas"
     | }
CaseClassMatchWithIf: (input: Any)String


scala> CaseClassMatchWithIf(Ferrari("California T","Automatic"))
res146: String = Ferrari called California T

scala> CaseClassMatchWithIf(Ford("Endeavour","Petrol"))
res147: String = Ford called Endeavour, runs on Petrol

scala> CaseClassMatchWithIf(Ford("Endeavour","Diesel"))
scala.MatchError: Ford(Endeavour,Diesel) (of class Ford)
  at .CaseClassMatchWithIf(<console>:16)
  ... 32 elided


This concludes the discussion on Pattern Matching in Scala.

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.

Sunday 24 December 2017

Introduction to Scala - IX

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 look at Operator Overloading.

All operators like + , - , * ,  / , %  in Scala mean the same as in other languages as Java and follow the infix notation. Infix notation means that the operator in placed in between the operands. For example, for multiplying two integers integer_1 and integer_2, we write:

integer_1 * integer_2

The other two notations are prefix notation and postfix notation. In prefix notation, the operator is placed before the operands, and in postfix notation, the operator is placed after the operands.

In Scala, all operators are methods. So, a multiplication operation between two integers can be written as:

3 * 5

or

3.*(5)

The results are shown below:

scala> 3 * 5
res42: Int = 15

scala> 3 . * (5)
res43: Int = 15


Since operators are methods in Scala, we can create a method, say, with name, * , to mean something different but imply the same product spirit in a new context. Let us see the program for multiplication of complex numbers. It is not straightforward as any complex number has a real part and an imaginary part. The formula for the product of complex numbers is shown below:

(a + bi) * (c + di) = (ac-bd) + (ad + bc)i        ----------------------------  (1)

This can be implemented in Scala by first defining a complex number class that takes two parameters, one for the real part and another for the imaginary part. Then, we can define a method with the symbol * that will return the product of the multiplication operation between the two complex numbers.

The class with the real and imaginary parameters is defined below:

class ComplexNumber(val real_part : Double, val imaginary_part : Double) 

We add the multiplication method as shown below:

class ComplexNumber(val real_part : Double, val imaginary_part : Double) {

def *(Second_Operand: ComplexNumber) = {
            new ComplexNumber(this.real_part*Second_Operand.real_part - this.imaginary_part*Second_Operand.imaginary_part, this.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*this.imaginary_part)
}

def multiply(Second_Operand: ComplexNumber) = {
            new ComplexNumber(this.real_part*Second_Operand.real_part - this.imaginary_part*Second_Operand.imaginary_part, this.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*this.imaginary_part)
}
  override def toString = real_part + " + " + imaginary_part + "i"
}


We have defined two identical methods called * and multiply doing the same multiplication of complex numbers as per formula (1) above. The toString is the Scala implementation equivalent to toString in Java to return a more meaningful object description.

Let us then run below commands to validate our code:

val x = new ComplexNumber(1.0,2.0)
val y = new ComplexNumber(3.0,4.0)

x*y

x.*(y)

x.multiply(y)


The results are shown below:

scala> class ComplexNumber(val real_part : Double, val imaginary_part : Double) {
     |
     | def *(Second_Operand: ComplexNumber) = {
     |             new ComplexNumber(this.real_part*Second_Operand.real_part - this.imaginary_part*Second_Operand.imaginary_part, this.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*this.imaginary_part)
     | }
     |
     | def multiply(Second_Operand: ComplexNumber) = {
     |             new ComplexNumber(this.real_part*Second_Operand.real_part - this.imaginary_part*Second_Operand.imaginary_part, this.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*this.imaginary_part)
     | }
     |   override def toString = real_part + " + " + imaginary_part + "i"
     | }
defined class ComplexNumber

scala> val x = new ComplexNumber(1.0,2.0)
x: ComplexNumber = 1.0 + 2.0i

scala> val y = new ComplexNumber(3.0,4.0)
y: ComplexNumber = 3.0 + 4.0i

scala> x*y
res56: ComplexNumber = -5.0 + 10.0i

scala> x.*(y)
res57: ComplexNumber = -5.0 + 10.0i

scala> x.multiply(y)
res58: ComplexNumber = -5.0 + 10.0i


The results are in line with formula (1).

Let us now rewrite the code so that the multiplication operation works as prefix notation.

class ComplexNumber1(val real_part : Double, val imaginary_part : Double){
 override def toString = real_part + " + " + imaginary_part + "i"
}

def *(First_Operand: ComplexNumber1,Second_Operand: ComplexNumber1):ComplexNumber1 = {
val a:Double = First_Operand.real_part*Second_Operand.real_part - First_Operand.imaginary_part*Second_Operand.imaginary_part;
val b:Double = First_Operand.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*First_Operand.imaginary_part;
new ComplexNumber1(a,b)}

def multiply(First_Operand: ComplexNumber1,Second_Operand: ComplexNumber1):ComplexNumber1 = {
val a:Double = First_Operand.real_part*Second_Operand.real_part - First_Operand.imaginary_part*Second_Operand.imaginary_part;
val b:Double = First_Operand.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*First_Operand.imaginary_part;
new ComplexNumber1(a,b)}


The results are shown below:

scala> class ComplexNumber1(val real_part : Double, val imaginary_part : Double){
     |  override def toString = real_part + " + " + imaginary_part + "i"
     | }
defined class ComplexNumber1

scala>

scala> def *(First_Operand: ComplexNumber1,Second_Operand: ComplexNumber1):ComplexNumber1 = {
     | val a:Double = First_Operand.real_part*Second_Operand.real_part - First_Operand.imaginary_part*Second_Operand.imaginary_part;
     | val b:Double = First_Operand.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*First_Operand.imaginary_part;
     | new ComplexNumber1(a,b)}
$times: (First_Operand: ComplexNumber1, Second_Operand: ComplexNumber1)ComplexNumber1

scala>

scala> def multiply(First_Operand: ComplexNumber1,Second_Operand: ComplexNumber1):ComplexNumber1 = {
     | val a:Double = First_Operand.real_part*Second_Operand.real_part - First_Operand.imaginary_part*Second_Operand.imaginary_part;
     | val b:Double = First_Operand.real_part*Second_Operand.imaginary_part + Second_Operand.real_part*First_Operand.imaginary_part;
     | new ComplexNumber1(a,b)}
multiply: (First_Operand: ComplexNumber1, Second_Operand: ComplexNumber1)ComplexNumber1


Let us test the above code with the same values that we used earlier and test the code:

val x = new ComplexNumber1(1.0,2.0)
val y = new ComplexNumber1(3.0,4.0)


*(x,y)

multiply(x,y)

The results are shown below:

scala> val x = new ComplexNumber1(1.0,2.0)
x: ComplexNumber1 = 1.0 + 2.0i

scala> val y = new ComplexNumber1(3.0,4.0)
y: ComplexNumber1 = 3.0 + 4.0i

scala> *(x,y)
res60: ComplexNumber1 = -5.0 + 10.0i

scala> multiply(x,y)
res61: ComplexNumber1 = -5.0 + 10.0i


The results are identical to the results from the earlier code.

Unary operators like +,-,!, or ~ can also be customized similar to the infix operators above. For example, we can find the absolute value of an integer as shown below:

class Absolute(val i:Int){
  def unary_! = if (i<0) -i else i
}


Note that to use ! as an operator, we have to use unary_! as the method name. To test we can use below code:

var x = new Absolute(1)
var y = new Absolute(-1)
!x
!y

The results are shown below:

scala> class Absolute(val i:Int){
     | def unary_! = if (i<0) -i else i
     | }
defined class Absolute


scala> var x = new Absolute(1)
x: Absolute = Absolute@20db19ff

scala> var y = new Absolute(-1)
y: Absolute = Absolute@578d5d02

scala> !x
res72: Int = 1

scala> !y
res73: Int = 1


In the last segment, we see codes for ++ and -- which are missing in Scala. The codes are shown for ++ and -- as a prefix unary operator below:

def ++(i:Int) = i + 1

def --(i:Int) = i - 1


The code to test it is below:

++(1)

--(1)

--(++(1))

The results are shown below:

scala> def ++(i:Int) = i + 1
$plus$plus: (i: Int)Int

scala> def --(i:Int) = i - 1
$minus$minus: (i: Int)Int

scala> ++(1)
res77: Int = 2

scala> --(1)
res78: Int = 0


scala> --(++(1))
res79: Int = 1


This concludes the Operator Overloading topic.

Introduction to Scala - VIII

We continue with more Scala on the topic of Singleton Objects in this post. 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 look at the way  Singleton Objects are declared and used in programs.

A Singleton Object is just like a class but, as the name says there can only one object or instance. We begin by taking a simple example as shown below:

object FirstObject {
def print {
println("Hello World!")
}
}


The results are shown below:

scala> object FirstObject {
     | def print {
     | println("Hello World!")
     | }
     | }
defined object FirstObject


When we try to instantiate it, we get below error:

scala> val Object = new FirstObject
<console>:11: error: not found: type FirstObject
       val Object = new FirstObject


To run it, we run below command as we normally run a static method in Java:

scala> FirstObject.print
Hello World!


 We already had a look at Singleton objects in the first post.The program is reproduced below:

object foobar {
/*Objects are single instances of their own definitions.
  It contains a method called main, the entry point of the program */
  def main(args: Array[String]){
    println("Hello, World!")
    // prints Hello, World
  }
}


The above program can be rewritten as shown below:

object foobar extends App{
    println("Hello, World!")
  }


Saving above lines in a file called AppDemo.scala and running it gives same result as above program:

F:\scala\examples>scalac AppDemo.scala

F:\scala\examples>scala -classpath . foobar
Hello, World!


In Scala, there is no concept of static fields or static methods. Instead, we have an object that can be used to define a single instance of a class with the desired functionality.

object foobar extends App{
    println("Hello, World!")
  }

In the above program, the main method from App trait is inherited. Two points of caution: The main method cannot be overridden and the whole body of the program is the main method itself.


The next topic we will see is that of Companion Objects. As mentioned before, in Scala classes do not have static fields or static methods. The way to implement static fields or static methods is to define a Companion Class and a corresponding Companion Object having the same name. Companion Objects have access to even the private members of the associated Companion Class. A simple example is shown below where a Companion Class and a Companion Object are defined. The members of the Companion Object are like static members of the Companion Class.

class Companion
object Companion {
var x:Int = 1
def Print:String = { "Hello, World!" }
}


The results are shown below:

scala> class Companion
defined class Companion

scala> object Companion {
     | var x:Int = 1
     | def Print:String = { "Hello, World!" }
     | }
defined object Companion
warning: previously defined class Companion is not a companion to object Companion.
Companions must be defined together; you may wish to use :paste mode for this.


Let is try to run using :paste as shown below:

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Companion
object Companion {
var x:Int = 1
def Print:String = { "Hello, World!" }
}

// Exiting paste mode, now interpreting.

defined class Companion
defined object Companion


Now, the members can be accessed as though they are static members of Companion as shown below:

scala> Companion.x
res0: Int = 1

scala> Companion.Print
res1: String = Hello, World!


This concludes the discussion on Companion Objects.

Wednesday 20 December 2017

Introduction to Scala - VII

We continue with more Scala on the topic of Case Classes in this post. 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 look at the way Case Classes are declared and instantiated in programs.

A Case Class is defined by the below statement:

case class Employee()

The results are shown below:

scala> case class Employee()
defined class Employee


We can add parameters to the class definition. The parameters by default are val. We can then instantiate by merely calling it as shown below:

case class EmployeeDetails(Id: Int, FirstName: String, LastName: String)

val employee1 = EmployeeDetails(1000,"John","Doe")

val employee2 = EmployeeDetails(1000,"John","Doe")

val employee3 = EmployeeDetails(1001,"Foo","Bar")

The results are shown below:

scala> case class EmployeeDetails(Id: Int, FirstName: String, LastName: String)
defined class EmployeeDetails

scala> val employee1 = EmployeeDetails(1000,"John","Doe")
employee1: EmployeeDetails = EmployeeDetails(1000,John,Doe)

scala> val employee2 = EmployeeDetails(1000,"John","Doe")
employee2: EmployeeDetails = EmployeeDetails(1000,John,Doe)

scala> val employee3 = EmployeeDetails(1001,"Foo","Bar")
employee3: EmployeeDetails = EmployeeDetails(1001,Foo,Bar)


We can call the employee details as shown below:

scala> employee1.FirstName + " " + employee1.LastName
res5: String = John Doe


But, we cannot assign any value to any of the parameters as the parameters are val by default.

Comparison using equals returns results based on values in the parameters as shown below :

scala> employee1 equals employee1
res8: Boolean = true

scala> employee1 equals employee2
res9: Boolean = true

scala> employee2 equals employee3
res10: Boolean = false


Comparison using == returns results based on values in the parameters as shown below :

scala> employee1 == employee1
res11: Boolean = true

scala> employee1 == employee2
res12: Boolean = true

scala> employee2 == employee3
res13: Boolean = false


Comparison using != that is opposite of == returns results based on values in the parameters as shown below :

scala> employee1 != employee1
res17: Boolean = false

scala> employee1 != employee2
res18: Boolean = false

scala> employee2 != employee3
res19: Boolean = true


Comparison using eq returns results based on references of the objects as shown below :

scala> employee1 eq employee1
res20: Boolean = true

scala> employee1 eq employee2
res21: Boolean = false

scala> employee2 eq employee3
res22: Boolean = false


Comparison using ne that is opposite of eq returns results based on references of the objects  as shown below :

scala> employee1 ne employee1
res23: Boolean = false

scala> employee1 ne employee2
res24: Boolean = true

scala> employee2 ne employee3
res25: Boolean = true


To replicate new objects, we can use copy method. We can set new values too.

val employee4 = employee1.copy(Id=1002,FirstName=employee3.FirstName)

println(employee4)

The results are shown below:

scala> val employee4 = employee1.copy(Id=1002,FirstName=employee3.FirstName)
employee4: EmployeeDetails = EmployeeDetails(1002,Foo,Doe)

scala> println(employee4)
EmployeeDetails(1002,Foo,Doe)


This concludes the discussion on Case Classes in Scala.

Tuesday 19 December 2017

Introduction to Scala - VI

In this post, we will look at the concept of  Currying in Scala. 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.

Let us first define a simple function and run it as shown below:

def product(x: Int,y: Int) = x * y

product(2,4)

The results are shown below:

scala> def product(x: Int,y: Int) = x * y
product: (x: Int, y: Int)Int

scala> product(2,4)
res12: Int = 8


The same function can be rewritten as a curried function taking single arguments multiple times as shown below:

def ProductCurrying(x: Int)(y: Int) = x * y

ProductCurrying(2)(4)

The results are shown below:

scala> def ProductCurrying(x: Int)(y: Int) = x * y
ProductCurrying: (x: Int)(y: Int)Int

scala> ProductCurrying(2)(4)
res13: Int = 8
 

A way to pass arguments one by one is shown below:

val interim = ProductCurrying(2) _

interim(4)

The results are shown below:

scala> val interim = ProductCurrying(2) _
interim: Int => Int = <function1>

scala> interim(4)
res17: Int = 8


The underscore indicates the blank argument.

ProductCurrying curried function can be rewritten as shown below:

def ProductCurrying1(x: Int) = (y: Int) => x * y

Then, we can pass the parameters one by one as shown below:

val interim = ProductCurrying1(2)
interim(4)


The results are shown below:

scala> def ProductCurrying1(x: Int) = (y: Int) => x * y
ProductCurrying1: (x: Int)Int => Int

scala> val interim = ProductCurrying1(2)
interim: Int => Int = <function1>

scala> interim(4)
res15: Int = 8


Defining a function with three arguments and then called to confirm is shown below:

def ProductCurrying2(x: Int) = (y: Int) => (z: Int) => x * y * z

ProductCurrying2(2)(4)(5)

The results are shown below:

scala> def ProductCurrying2(x: Int) = (y: Int) => (z: Int) => x * y * z
ProductCurrying2: (x: Int)Int => (Int => Int)

scala> ProductCurrying2(2)(4)(5)
res22: Int = 40


This concludes the discussion on Currying in Scala.

Monday 18 December 2017

Introduction to Scala - V

We continue with more Scala on the topic of Mixins in this post. 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 look at more of traits in the form of Mixins.

We have already seen Traits in this post. Mixins are traits that can be used to compose a class. The first example is very similar to the one we have seen in the earlier post:

class Class{
  def Printx(Value: Long): Unit = {
    println("Value in Class is " + Value)
  }
}

trait trait6 { def method6 }

trait trait7 extends trait6 { def method6 { println("method7 in trait7") } }

val NewClass = new Class with trait7 {
  override def Printx(Value: Long): Unit = {
  method6
  println("Value in NewClass is " + Value)
  super.Printx(Value)
  }
}


NewClass.Printx(5)

The results are shown below:

scala> class Class{
     |   def Printx(Value: Long): Unit = {
     |     println("Value in Class is " + Value)
     |   }
     | }
defined class Class

scala> trait trait6 { def method6 }
defined trait trait6

scala> trait trait7 extends trait6 { def method6 { println("method7 in trait7") } }
defined trait trait7

scala> val NewClass = new Class with trait7 {
     |   override def Printx(Value: Long): Unit = {
     |   method6
     |   println("Value in NewClass is " + Value)
     |   super.Printx(Value)
     |   }
     | }
NewClass: Class with trait7 = $anon$1@68702e03

scala> NewClass.Printx(5)
method7 in trait7
Value in NewClass is 5
Value in Class is 5


In the above example, we define a class called Class that contains a method called Printx. Next, trait6 is defined having abstract method called method6. trait7 inherits trait6 and implements method6. We then instantiate Class with Mixin trait, trait7 with keyword, with. Note that Printx is overridden with a new definition. If Printx is not overridden, NewClass would have inherited Printx as implemented in trait7. Note also that while the signature of Printx remains the same as seen from outside, internals are modified. Lastly, we call Printx and the results are in line with the definition of Printx with Mixin.

This concludes the topic Mixins.