Scala – Tuples & Lists

=====================================================
Tuples
=====================================================
A Tuple is a generalization of a collection of two, three, four, and more values. Each value can have its own type.

scala> val twoInts = (5,10)
	twoInts: (Int, Int) = (5,10)
 
scala> val twoStrings = ("Hello", "World")
	twoStrings: (String, String) = (Hello,World)
 
scala> val threeDoubles = (1.11, 2.22, 3.33)
	threeDoubles: (Double, Double, Double) = (1.11,2.22,3.33)
 
scala> val intAndString = (1, "Good Evening")
	intAndString: (Int, String) = (1,Good Evening)
 
scala> val mixedUp = (1, "Vinay Chauhan", 90.50)
	mixedUp: (Int, String, Double) = (1,Vinay Chauhan,90.5)

The elements of a Tuple can be recovered in a few different ways. One way is to use a Tuple when initializing some variables, each of which takes on the value of the corresponding position in the Tuple on the right side of the equal sign.

scala> var (firstInt,secondInt) = twoInts
	firstInt: Int = 5
	secondInt: Int = 10

scala> firstInt
	res39: Int = 5	

Similarly, we could do the actvity for other tuples. 

scala> var (rollNo,name,marks) = mixedUp
	rollNo: Int = 1
	name: String = Vinay Chauhan
	marks: Double = 90.5

scala> rollNo
	res41: Int = 1

scala> name
	res42: String = Vinay Chauhan

scala> marks
	res43: Double = 90.5

***********************************
Few Tips
***********************************	
Another way to access the values in a Tuple is via indexation, using “_n” where n is the index of the item you want.

scala> print(mixedUp._1)
	1
scala> print(mixedUp._2)
	Vipin Chauhan
scala> print(mixedUp._3)
	90.5

***********************************
Few Tips
***********************************
An alternate form of creating a 2-sized tuple is with the relation operator (->). This is a popular shortcut for representing key-value pairs in tuples:	

scala> val fruitData = "FruitKing" -> "Mango"
	fruitData: (String, String) = (FruitKing,Mango)

scala> fruitData._1
	res3: String = FruitKing

scala> fruitData._2
	res4: String = Mango

=====================================================
Lists
=====================================================
Lists are collections of ordered items that will be familiar to anyone who has done any shopping. Tuples are obviously related to lists, but they are less versatile in that they must be created in a single statement, they have a bounded length (about 20 or so), and they don’t support operations that perform computations on all of their elements. In Scala, we can create lists of Strings, Ints, and Doubles (and more).

scala> val fruitList = List("Mango","Orange","PineApple")
	fruitList: List[String] = List(Mango, Orange, PineApple))

scala> fruitList.head
	res0: String = Mango

scala> fruitList.tail
	res2: List[String] = List(Orange, PineApple)

scala> fruitList
	res3: List[String] = List(Mango, Orange, PineApple)

scala> fruitList(1)
	res4: String = Orange

scala> fruitList(2)
	res5: String = PineApple

scala> for(data <- fruitList) println(data) Mango Orange PineApple scala> val oddList = List(1,3,5,7);
	oddList: List[Int] = List(1, 3, 5, 7)

We see that Scala responds that a List has been created, along with brackets around the type of the elements it contains. So, List[Int] is read as “a List of Ints” and so on. This is to say that List is a parameterized data structure: it is a container that holds elements of specific types. 

***********************************
Few Tips
***********************************	
We can also create Lists with mixtures of types.

scala> val intsAndDoubles  = List (1,1.5,2,2.5)
	intsAndDoubles: List[Double] = List(1.0, 1.5, 2.0, 2.5)

scala> val embeddedList = (fruitList,oddList);
	embeddedList: (List[String], List[Int]) = (List(Mango, Orange, PineApple),List(1, 3, 5, 7))

***********************************
Use Case for Reducer 
***********************************
scala> val numbers = List(1,2,3,4,5)
	numbers: List[Int] = List(1, 2, 3, 4, 5)

scala> val total = numbers.reduce((a:Int, b:Int) => a+b)
	total: Int = 15

	
=========================================================================
List methods
=========================================================================
scala> fruitList.length
	res48: Int = 3

Comments: The notation variable.method indicates that you are invoking a function that is specific to the type of that variable on the value in that variable. Scala is an object-oriented language, which means that every value has a set of actions that comes with it. Which actions are available depends on its type. 

scala> 2.+(3)
	res49: Int = 5

scala> "Good".+("Evening")
	res51: String = GoodEvening	

Comments: Lets return to Lists and what we can do with them. “Addition” of two lists is their concatenation and is indicated with “++“.

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

scala> val evenList = List (2,4,6,8);
	evenList: List[Int] = List(2, 4, 6, 8)

scala> val completeList = oddList ++ evenList
	completeList: List[Int] = List(1, 3, 5, 7, 2, 4, 6, 8)

Comments: We can append a single item to the front of a List with “::“.

scala> val completeList = 0 :: oddList ++ evenList
	completeList: List[Int] = List(0, 1, 3, 5, 7, 2, 4, 6, 8)

And sort a list with sorted, and reverse it with reverse, and do both in sequence

scala> completeList.sorted
	res52: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8)

scala> completeList.reverse
	res54: List[Int] = List(8, 6, 4, 2, 7, 5, 3, 1, 0)

scala> completeList.sorted.reverse
	res55: List[Int] = List(8, 7, 6, 5, 4, 3, 2, 1, 0)

Note: List is immutable: you cannot change it, so all of these operations will always return new Lists. 

scala> val myList = completeList.sorted
	myList: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8)

scala> myList(2);
	res57: Int = 2

Another useful method is slice, which gives you a sublist from one index up to, but not including, another.
scala> myList.slice(2,6)
	res58: List[Int] = List(2, 3, 4, 5)

Therefore, the slice gave us a list with the elements from index 2 (the third element) up to index 5 (the sixth element).

***********************************
Few Tips
***********************************
On lists that contain numbers, we can use the sum method.
scala> myList.sum
	res60: Int = 36

One thing we often want to do with lists is obtain a String representation of their contents in some visually useful way. For example, we might want a fruitList to be a String with one item per line, or a list of Ints to have a comma between each element. The mkString method does just what we need.

scala> fruitList.mkString("\n")
	res61: String =
	Mango
	Orange
	PineApple

Want to know if a list contains a particular element? Use contains on the list.
scala> fruitList.contains("Apple")
	res63: Boolean = false

scala> fruitList.contains("Mango")
	res64: Boolean = true
Advertisements

Functions in Scala

Variables are more useful when used in the context of functions in which a variable like x can be injected with different values by the user of a function. Let’s consider converting degrees Fahrenheit to Celsius. To convert 87, 92, and 100 from Fahrenheit to Celcius, we could do the following.

 
scala> (87 - 32) * 5 / 9.0
	res32: Double = 30.555555555555557

scala> (92 - 32) * 5 / 9.0
	res33: Double = 33.333333333333336

Obviously, there is a lot of repetition here. Functions allow us to specify the common parts of such calculations, while allowing variables to specify the parts that may be different. In the conversion case, the only thing that changes is the temperature reading in Fahrenheit. Here’s how we declare the appropriate function in Scala.

 
-------------------------------------------------------------------------
def <identifier>(<identifier>: <type>[, ... ]): <type> = <expression>
-------------------------------------------------------------------------

scala> def f2c (x : Double) =  (x - 32) * 5 / 9.0
	f2c: (x: Double)Double

Breaking this down, we have:
    (1) def is a Scala keyword indicating that a function is being defined
    (2) f2c (Fahrenheit to Celsius) is the name given to the function
    (3) (x: Double) is the parameter to the function, which is a variable named x of type Double
    (4) (x – 32) * 5/9.0 is the body of the function, which will take the value given by the user of the function	
	
scala> f2c(87)
	res34: Double = 30.555555555555557

scala> f2c(92)
	res36: Double = 33.333333333333336

=====================================================
Procedures
=====================================================
A procedure is a function that doesn’t have a return value. Any function that ends with a statement, such as a println() call, is also a procedure. If you have a simple function without an explicit return type that ends with a statement, the Scala compiler will infer the return type of the function to be Unit

 
scala> def myFunction = {
  println("Hai");
  println("Good Afternoon");
}
Output:- 
	myFunction: Unit

scala> myFunction
	Hai
	Good Afternoon

scala> def log(d: Double): Unit = println(f"Got Value : $d%.2f")
	log: (d: Double)Unit

scala> log(2.547)
	Got Value : 2.55

=====================================================
Functions With Empty Parentheses
=====================================================

scala> def hi = "Hi, Good Evening"
	hi: String

scala> hi
	res0: String = Hi, Good Evening
	
--------------------------------------------------------------------------------
def <identifier>: <type> = <expression>
--------------------------------------------------------------------------------
scala> def hi : String = "Hi, Very Good Evening"
	hi: String

scala> hi
	res1: String = Hi, Very Good Evening	

-------------------------------------------------------------------------
def <identifier>()[: <type>] = <expression>
-------------------------------------------------------------------------

scala> def message() : String = "Good Morning"
	message: ()String

scala> message()
	res0: String = Good Morning

scala> message
	res1: String = Good Morning

=====================================================
Recursive Functions
=====================================================

 
scala> def power(x : Int, y : Int) : Int = {
   if (y>=1){
     x * power(x, y-1);
   }   
   else{
     1
   }   
 }
	
scala> power(2,3)
	res2: Int = 8	

=====================================================
Calling Nested Functions
=====================================================

scala> def max(a:Int, b:Int, c:Int) = {
   def max(d:Int, e:Int) = if(d > e) d else e
   max (a, max(b,c))
 }
max: (a: Int, b: Int, c: Int)Int

scala> max (2,5,7)
	res3: Int = 7

=====================================================
Calling Functions With Named Parameters
=====================================================

-------------------------------------------------------------------------
<function name>(<parameter> = <value>)
-------------------------------------------------------------------------
scala> def greetings(prefix: String, name: String) = s"$prefix. $name"

scala> val myGreetings = greetings("Ms", "Brown")
myGreetings: String = Ms. Brown

=====================================================
Calling Functions Parameters With Default Values
=====================================================

 
scala> def greetings(prefix: String = "", name: String) = s"$prefix $name"
	greetings: (prefix: String, name: String)String

scala> val myGreetings = greetings(name="Tom");
	myGreetings: String = " Tom"

=====================================================
Calling Functions Using VarArg Parameters
=====================================================

 
scala> def sum(items: Int*): Int = {
  var sum = 0;
  for(i <- items) {
    sum = sum + i;
  }
  sum;
}

scala> sum(10,20,30)
	res4: Int = 60

=====================================================
Calling Functions Using Parameter Groups
=====================================================

 
scala> def max(x: Int)(y: Int) = if (x > y) x else y
	max: (x: Int)(y: Int)Int

scala> max(10)(20)
	res5: Int = 20

=====================================================
Calling Higher-Order Functions
=====================================================

 
scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}
safeStringOperation: (value: String, func: String => String)String

scala> def reverser(value : String) = {
  value.reverse
  }
reverser: (value: String)String

scala> safeStringOperation(null, reverser)
	res5: String = null

scala> safeStringOperation("Apple",reverser)
	res6: String = elppA

=====================================================
Function Literals
=====================================================

scala> val getDouble = (x: Int) => x*2
	getDouble: Int => Int = <function1>

scala> getDouble(2)
	res0: Int = 4

=====================================================
Use Case-1 (Higher-Order Functions + Function Literals)
=====================================================

scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}
safeStringOperation: (value: String, func: String => String)String
	
scala> safeStringOperation("Apple", (data:String)=>data.reverse)
	res2: String = elppA	

=====================================================
Use Case-2 (Higher-Order Functions + Function Literals)
=====================================================

		
scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}
safeStringOperation: (value: String, func: String => String)String

scala> safeStringOperation("Apple", data=> data.reverse)
res3: String = elppA

Comments: No need to specify the data type. It is inferred from the first parameter

=====================================================
Placeholder Syntax
=====================================================

 
scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}

scala> safeStringOperation("Apple", _.reverse)
res4: String = elppA

Scala Expressions, Variables and Basic Types

We’ll use Scala REPL for entering Scala expressions and seeing what the result of evaluating them is. REPL stands for Read-Eval(uate)-Print-Loop, which means it is a program that
(1) reads the expressions you type in,
(2) evaluates them using the Scala Compiler,
(3) prints out the result of an evaluation, and then
(4) waits for you to enter further expressions.

=====================================================
Scala in Action from Command Prompt
=====================================================

 
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\>scala
	Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
	Type in expressions for evaluation. Or try :help.
scala> 

Comments: The scala> line is the prompt that the REPL is waiting for you to enter expressions.

=====================================================
Case Study – 1
=====================================================

	
scala> "Hello World"
	res8: String = Hello World

scala> 2017
	res9: Int = 2017

scala> "2000"
	res10: String = 2000

scala> 3+4
	res11: Int = 7

scala> "2" + "3"
	res13: String = 23

scala> println("Hi,\nGood Morning");
	Hi,
	Good Morning	

=====================================================
Case Study – 2
=====================================================

	
scala> print ("Hello World")
	Hello World
scala> print (3+4)
	7

Comments: Following is the workflow for above statement:- 
	(1) Scala evaluates 3 + 4, which is 7.
	(2) Scala passes that value to the command prompt.
	(3) print outputs “7"

We often need to store the result of evaluating an expression to a variable for later use
scala> val x = 3+4
	x: Int = 7
scala> print(x)
	7

Here, x is a variable, which we’ve indicate by prefacing it with val, which indicates it is a fixed variable whose value cannot change. We  can choose the names for variables, but they must follow some rules.
    (1) Variable names may contain: letters, numbers, underscore
    (2) They should not start with a number
    (3) They should not be identical to one of the “reserved words” that Scala has already defined, such as for, if, val, var, etc.

***********************************
Few Working Tips
***********************************
scala> print(x)
	5
scala> print (x+5)
	10
scala> x+10
	res23: Int = 15
scala> x
	res25: Int = 5
scala> 7/2
	res26: Int = 3
scala> 7.0/2.0
	res27: Double = 3.5

=====================================================
Case Study – 3
=====================================================

 	
scala> val a : Int = 20    // We are doing naming here with help of "val a"
	a: Int = 20

Syntax :- val <identifier> [:<type>] = <expression>

scala> print (a)
	20
scala> a /2
	res29: Int = 10

Comments: The a : Int portion of the line indicates that the variable a has the type Int. Here are some examples of other variables with different types.

scala> val b: Double = 2.25
	b: Double = 2.25

scala> val c: String = "Hello world"
	c: String = Hello world

scala> val pi: Int = 3.14
	<console>:11: error: type mismatch;
	 found   : Double(3.14)
	 required: Int
		   val pi : Int = 3.14
						  
Comments: Importantly, we cannot assign the variable a type that conflicts with the result of the expression. Here, we try to assign a Double value to a variable of type Int, and Scala reports an error.
					  
scala> val pi: Double = 3.14
	pi: Double = 3.14

scala> val atSymbol: Char = '@'
	atSymbol: Char = @

scala> val l: Long = 20
	l: Long = 20

scala> val i: Int = l.toInt
	i: Int = 20		

=====================================================
Case Study – 4
=====================================================

 
In addition to variables declared with val, Scala allows variables to be declared with var — these variable can have their values reassigned. A few examples are the easiest way to see the difference and syntax is var <identifier>[:<type>] = <expression>

scala> val a = 5
	a: Int = 5

scala> a = 10
<console>:12: error: reassignment to val
       a =10
         ^
scala> var b = 5
	b: Int = 5
	
scala> b = 10
	b: Int = 10

scala> b
	res31: Int = 10

=====================================================
Case Study – 5
=====================================================

 
scala> val x: Int = 5
	x: Int = 5

scala> x 
	res0: Int = 5

scala> x * 2
	res1: Int = 10

scala> res0 * res1
	res2: Int = 50

=====================================================
Case Study – 6
A multiline String can be created using triple-quotes. Multiline strings are literal, and so do not recognize the use of backslashes as the start of special characters:

=====================================================

 
scala> val greeting = """She suggested reformatting the file
     | by replacing tabs (\t) with newlines (\n);
     | "Why do that?", he asked. """
greeting: String =
"She suggested reformatting the file
by replacing tabs (\t) with newlines (\n);
"Why do that?", he asked. "	

=====================================================
Case Study – 7 :: String Interpolation
=====================================================

 
scala> val item = "apple"
	item: String = apple

scala> s"How do you like ${item}s?"
	res0: String = How do you like apples?

scala> s"Fish n chips n vinegar, ${"pepper "*3}salt"
	res1: String = Fish n chips n vinegar, pepper pepper pepper salt

=========================================================================
Case Study – 8 :: An Overview Of Scala Types
=========================================================================

 
scala> val isTrue = !true
isTrue: Boolean = false

scala> val isFalse = !true
isFalse: Boolean = false

scala> val unequal = (5 != 6)
unequal: Boolean = true

scala> val isLess = (5 < 6) 
isLess: Boolean = true 

scala> val unequalAndLess = unequal & isLess
unequalAndLess: Boolean = true

scala> val definitelyFalse = false && unequal
definitelyFalse: Boolean = false