Introduction to
__
________ ___ / / ___
/ __/ __// _ | / / / _ |
__\ \/ /__/ __ |/ /__/ __ |
/____/\___/_/ |_/____/_/ | |
|/ Programming Language
Saleem Ansari (@tuxdna
)
Scala stands for "scalable language" -- designed to grow with demands of its users.
What makes Scala a "scalable language"?
Compare it to other languages such as Python, Ruby etc., which are interpretted, dynamically typed and so on.
scala
-- The Scala Interperter ( think of java
)scalac
-- The Scala Compiler ( think of javac
)sbt
-- Scala Build Tool ( think of Ant, Ivy, Maven etc. )Scala REPL - Read Eval Print Loop
1 $ scala
2 Welcome to Scala version 2.9.1 (OpenJDK 64-Bit Server VM, Java 1.7.0_51).
3 Type in expressions to have them evaluated.
4 Type :help for more information.
5
6 scala> println("Hello Scala World!")
7 Hello Scala World!
8
9 scala>
Data Types: ( all integers are signed two's complement )
Byte
(8bit), Short
(16bit), Int
(32bit), Long
(64bit)Char
(16 bit unicode character), String
(squence of Chars)Float
(32bit), Double
(64bit)Boolean
: either true
or false
Literals
1
, 0.123
, 12L
, 'a'
, "String"
'identifier
1 scala> val x = 10
2 x: Int = 10
3 scala> x = 12
4 <console>:8: error: reassignment to val
5 x = 12
6 ^
7
8 scala> var y = 10
9 y: Int = 10
10 scala> y = 12
11 y: Int = 12
In addition to Java collections Scala provides:
List
( similar to java.util.LinkedList
)Array
( similar to Java Array )Set
( similar to java.util.Set
)Map
( similar to java.util.Map
)Tuple
( Java doesn't have a Tuple )scala.collection.immutable
)scala.collection.mutable
)Immutability: a collection once create can not be changed in itself, however we can compose a collection from other collections. Such collections have big benefits:
1 scala> val lst = List(1,2,3,4,5,6,7,8,10)
2 lst: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 10)
3
4 scala> val arr = Array(1,2,3,4,5,6,7,8,9,10)
5 arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
1 scala> val radiation = Map('a' -> "alpha", 'o' -> "omega",
2 'g' -> "gamma")
3 scala> radiation('g')
4 res5: String = gamma
1 scala> val T = Set("casey", "drew", "jade")
2 scala> val V = Set("drew", "jade", "glen")
3 scala> val S = Set("alex", "hunter", "casey", "drew")
4 scala> val U = V union T union S union
5 Set("blair", "erin", "francis", "era")
6 scala> val commonSet = S & T & V
7 commonSet : scala.collection.immutable.Set[String] = Set(drew)
1 scala> val tuple1 = Tuple1(1)
2 tuple1: (Int,) = (1,)
3
4 scala> val tuple2 = ('a', 1)
5 tuple2: (Char, Int) = (a,1)
6
7 scala> val tuple3 = ('a', 1, "name")
8 tuple3: (Char, Int, java.lang.String) = (a,1,name)
9
10 scala> tuple1._1
11 res0: Int = 1
12 scala> tuple2._2
13 res1: Int = 1
14 scala> tuple3._1
15 res2: Char = a
16 scala> tuple3._3
17 res3: String = name
1 scala> import java.util.Calendar
2 import java.util.Calendar
3
4 scala> val now = Calendar.getInstance()
5 now: java.util.Calendar = java.util.GregorianCalendar[....]
6
7 scala> val hour = now.get(Calendar.HOUR_OF_DAY)
8 hour: Int = 19
9
10 scala> println( if(hour < 12) "good afternoon" else "good morning")
11 good morning
1 scala> val numbers = (1 to 10) toList
2 numbers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
3
4 scala> for(n <- numbers) print(n + " ")
5 1 2 3 4 5 6 7 8 9 10
6
7 scala> var index = 0
8 index: Int = 0
9
10 scala> while(index < numbers.length) {
11 print(numbers(index) + " "); index += 1
12 }
13 1 2 3 4 5 6 7 8 9 10
14
15 scala> var index = 0
16 scala> do {
17 print(numbers(index) + " ")
18 index += 1
19 } while (index < numbers.length)
20 1 2 3 4 5 6 7 8 9 10
1 scala> val dow = now.get(Calendar.DAY_OF_WEEK)
2 dow: Int = 3
3
4 scala> dow match {
5 case 1 => "Sunday"
6 case 2 => "Monday"
7 case 3 => "Tuesday"
8 case 4 => "Wednesday"
9 case 5 => "Thursday"
10 case 6 => "Friday"
11 case 7 => "Saturday"
12 }
13 res20: java.lang.String = Tuesday
14
15 scala> dow match {
16 case x if x == 1 || x == 7 => "Weekend"
17 case _ => "Workday"
18 }
19 res21: java.lang.String = Workday
1 val text =
2 """|Hello Scala World
3 |Scala is a wonderful language
4 |OO + FP make Scala wonderful
5 |You should also try Scala""".stripMargin('|')
6
7 val nextToScala = """.*\bScala (\w+).*""".r
8 > nextToScala : scala.util.matching.Regex = .*\bScala (\w+).*
9
10 for (line <- text.split("\n")) yield line match {
11 case nextToScala(w) => w
12 case _ => ""
13 }
14 > res0: Array[String] = Array(World, is, wonderful, "")
1 scala> var divisor = 0
2 divisor: Int = 0
3
4 scala> def divide(n: Int) = 1 / divisor
5 divide: (n: Int)Int
6
7 scala> def divide(n: Int) = n / divisor
8 divide: (n: Int)Int
9
10 scala> try { divide(10) } catch {
11 case e: ArithmeticException => "Check your calculations!"
12 }
13 res34: Any = Check your calculations!
14
15 scala> divisor = 2
16 divisor: Int = 2
17
18 scala> try { divide(10) } catch {
19 case e: ArithmeticException => "Check your calculations!"
20 }
21 res35: Any = 5
Lambda calculus: (closure, functions and values, higher order functions, recursion)
1 scala> def f(x: Double) = x * x
2 f: (x: Double)Double
3
4 scala> def g(y: Double) = 1 / y
5 g: (y: Double)Double
1 scala> def gof(x: Double) = g(f(x))
2 gof: (x: Double)Double
3
4 scala> gof(2)
5 res42: Double = 0.25
6
7 scala> gof(4)
8 res43: Double = 0.0625
Hallmarks of Functional Programming
1 val lst = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
2 lst.map(x => x * x)
3 > res0: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
4
5 lst.filter(x => x % 3 == 0)
6 > res1: List[Int] = List(3, 6, 9)
7
8 lst.reduce((x, y) => x + y)
9 > res2: Int = 55
10
11 lst.fold(0)((x, y) => x + y)
12 > res3: Int = 55
1 lst.reduce((x, y) => x * y)
2 > res4: Int = 3628800
3
4 lst.fold(1)((x, y) => x * y)
5 > res5: Int = 3628800
6
7 lst.reduceLeft((x, y) => x * y)
8 > res6: Int = 3628800
9
10 lst.foldLeft(1)((x, y) => x * y)
11 > res7: Int = 3628800
12
13 lst.reduceRight((x, y) => x * y)
14 > res8: Int = 3628800
15
16 lst.foldRight(1)((x, y) => x * y)
17 > res9: Int = 3628800
1 val result = (1 to 20)
2 .map(x => x * x)
3 .groupBy(_ % 5).par
4 .map { y => y._2.sum }
5 .sum
6 > result : Int = 2870
A function is treated same as any other variable. Which means we can store a function in a variable. According to Wikipedia:
Example:
1 def add(a: Int, b: Int) = a + b
2 > add: (a: Int, b: Int)Int
3 val myfunc = (a: Int, b: Int) => a + b
4 > myfunc : (Int, Int) => Int = <function2>
5 val otherfunc = add _
6 > otherfunc : (Int, Int) => Int = <function2>
7
8 add(2, 4) // > res0: Int = 6
9 myfunc(4, 5) // > res1: Int = 9
10 otherfunc(6, 7) // > res2: Int = 13
11
12 (x: Int, y: Int, z: Int) => x * y * z
13 > res3: (Int, Int, Int) => Int = <function3>
14
15 ((x: Int, y: Int, z: Int) => x * y * z)(5,4,3)
16 > res4: Int = 60
In mathematics and computer science, a higher-order function (also functional form, functional or functor) is a function that does at least one of the following:
1 scala> def transform(fn: (Int) => Int, number: Int) = fn(number)
2 transform: (transformer: Int => Int, number: Int)Int
3
4 scala> val plus5 = transform( (x: Int) => x + 5, _: Int)
5 plus5: Int => Int = <function1>
6
7 scala> val into3 = transform( (x: Int) => x * 3, _: Int)
8 into3: Int => Int = <function1>
9
10 scala> plus5(6)
11 res6: Int = 11
12
13 scala> into3(6)
14 res7: Int = 18
A Pure Function has no side effects (memory or I/O). This means:
1 scala> def stat(num: List[Int]) = { (num.sum, num.sum/num.length.toDouble) }
2 stat: (num: List[Int])(Int, Double)
3
4 scala> val list1 = List(1,2,3,4,5); val list2 = List(6,7,8,9,10)
5 list1: List[Int] = List(1, 2, 3, 4, 5)
6 list2: List[Int] = List(6, 7, 8, 9, 10)
7
8 scala> (stat(list1), stat(list2))
9 res57: ((Int, Double), (Int, Double)) = ((15,3.0),(40,8.0))
A function can call itself, over and over, until a base-case is reached.
1 scala> def factorial(n: Int): Int = {
2 if(n=0) 1
3 else n*factorial(n-1)
4 }
5 factorial: (n: Int)Int
6
7 scala> factorial(5)
8 res2: Int = 120
Lazy val
1 scala> lazy val a = b + 1; lazy val b = 1;
2 a: Int = <lazy>
3 b: Int = <lazy>
4
5 scala> a
6 res36: Int = 2
7
8 scala> b
9 res37: Int = 1
Call by name
1 scala> def withinTx(block: () => Unit) = {
2 println("Begin TX"); block() ; println("End TX")
3 }
4 withinTx: (block: () => Unit)Unit
5
6 scala> withinTx { () => println("Performing operation") }
7 Begin TX
8 Performing operation
9 End TX
10
11 scala> def insideTx(block: => Unit) = {
12 println("Begin TX"); block ; println("End TX")
13 }
14 insideTx: (block: => Unit)Unit
15
16 scala> insideTx { println("Performing operation") }
17 Begin TX
18 Performing operation
19 End TX
Just like java has Interface, Scala has Traits, but with definitions.
1 trait Perishable {
2 def name: String
3 def lifespan: Int
4 }
5
6 class Person {
7 // class body
8 def age() = { 19 }
9 }
10
11 object TheCat {
12 // object body
13 def sayHelloNTimes(n: Int, name: String): String = { "" }
14 }
Java:
1 interface Animal {
2 public String name();
3 public int lifespan();
4 }
1 class Animal {
2 // class body
3 val age = 10
4 def method1(p1: Int, p2: String): String = {
5 /* some operations here */
6 }
7 }
8
9 val a = new Animal // this is an instance of class Animal
Object is not the same as an instance of a class
Object is singleton
1 object Animal {
2 // object body
3 val age = 10 // object member
4 def method1(p1: Int, p2: String): String = { /* some operations here */ }
5 }
6
7 println(Animal.age)
Objects name same as class name, and inside same source file
1 class Animal(name: String, lifespan: Int) {
2 def makeNoise(volume: Int): String = {
3 name + " at volume: " + volume
4 }
5 }
6
7 object Animal {
8 def apply(name: String, lifespan: Int) = new Animal(name, lifespan)
9 }
10
11 val a0 = new Animal("Mammoth", 100)
12 val a1 = Animal("Elephant", 40)
1 def veryLoud(animal: { def makeNoise(vol: Int): String }) = {
2 animal.makeNoise(10)
3 }
4
5 val a0 = new Animal("Mammoth", 100)
6 veryLoud(a0)
Stroke Engines
Steam Engine
1 package oop;
2 import java.util.Arrays;
3 public class MyEngines {
4 enum FuelLevel {Empty, Reserve, Half, Full}
5 interface Startable { public void start(); }
6 interface Stoppable { public void stop(); }
7
8 abstract class Engine implements Startable, Stoppable { ... }
9 class TwoStrokeEngine extends Engine { ... }
10 class FourStrokeEngine extends Engine { ... }
11
12 interface Make { ... }
13 class SteamEngine extends Engine implements Make { ... }
14
15 public static void main() { ... }
16 }
Continued on next slide...
1 abstract class Engine implements Startable, Stoppable {
2 int horsePower;
3 FuelLevel fuelLevel;
4 boolean running = false;
5 public Engine(int hp, boolean state, FuelLevel fl) {
6 this.horsePower = hp; this.running = state; this.fuelLevel = fl;
7 }
8 @Override
9 public void start() {
10 switch (fuelLevel) {
11 case Empty:
12 System.out.println("Cannot start without fuel.");
13 default:
14 if (!running) {
15 running = true;
16 System.out.println("Engine started");
17 } else System.out.println("Engine already started");
18 }
19 }
20 @Override
21 public void stop() {
22 if (running) {
23 running = false; System.out.println("Engine stopped");
24 }
25 }
26 @Override
27 public String toString() {
28 return String.format(
29 "Engine(running: %s, fuelLevel: %s, horsePower: %d BHP)", running, fuelLevel, horsePower);
30 }
31 }
1 class TwoStrokeEngine extends Engine {
2 String model;
3 public TwoStrokeEngine(int hp, boolean state, FuelLevel fl) {
4 super(hp, state, fl);
5 }
6 @Override
7 public String toString() {
8 return "TwoStroke" + super.toString();
9 }
10 }
11
12 class FourStrokeEngine extends Engine {
13 String model;
14 public FourStrokeEngine(int hp, boolean state, FuelLevel fl) {
15 super(hp, state, fl);
16 }
17 @Override
18 public String toString() {
19 return "FourStroke" + super.toString();
20 }
21 }
1 interface Make {
2 public String make();
3 }
4
5 class SteamEngine extends Engine implements Make {
6 String model = "IndianRailways";
7 public SteamEngine(int hp, boolean state, FuelLevel fl) {
8 super(hp, state, fl);
9 }
10 public SteamEngine(int hp, boolean state, FuelLevel fl, String modelName) {
11 this(hp, state, fl);
12 this.model = modelName;
13 }
14 @Override
15 public String make() { return "SteamEngine - " + model; }
16 @Override
17 public String toString() {
18 return "Steam" + super.toString();
19 }
20 }
1 public static void main(String[] args) {
2
3 MyEngines me = new MyEngines();
4
5 FourStrokeEngine e1 = me.new FourStrokeEngine(40, false,
6 FuelLevel.Empty);
7 System.out.println(e1);
8 e1.start(); // won't start
9 e1.fuelLevel = FuelLevel.Full;
10 e1.start(); // will start: fuel-tank is now full
11 System.out.println(e1 + "\n");
12
13 TwoStrokeEngine e2 = me.new TwoStrokeEngine(26, false, FuelLevel.Full);
14 System.out.println(e2);
15 e2.start();
16 System.out.println(e2 + "\n");
17
18 SteamEngine e3 = me.new SteamEngine(1800, true, FuelLevel.Reserve);
19 System.out.println(e3);
20 System.out.println(e3.make() + "\n");
21
22 Engine[] myengines = { e1, e2, e3 };
23 System.out.println(Arrays.asList(myengines) + "\n");
24 }
1 package oop
2 object engine {
3 object FuelLevel extends Enumeration {
4 type FuelLevel = Value
5 val Empty, Reserve, Half, Full = Value
6 }
7 import FuelLevel._
8
9 trait Stoppable {
10 var running: Boolean
11 var fuelLevel: FuelLevel
12 def stop = if (running) {running = false; println("Engine stopped")}
13 }
14
15 trait Startable {
16 var running: Boolean
17 var fuelLevel: FuelLevel
18 def start = fuelLevel match {
19 case FuelLevel.Empty => println("Cannot start without fuel.")
20 case _ if ! running => {
21 running = true; println("Engine started")
22 }
23 case _ => println("Engine already running")
24 }
25 }
1 class Engine(hp: Int, state: Boolean, fl: FuelLevel)
2 extends Startable with Stoppable {
3 val horsePower = hp
4 var fuelLevel = fl
5 var running = state
6 override def toString="Engine(running: %s, fuelLevel: %s, horsePower: %dBHP)"
7 .format(running, fuelLevel, horsePower)
8 }
9 class TwoStrokeEngine(hp: Int, state: Boolean, fl: FuelLevel)
10 extends Engine(hp, state, fl) {
11 override def toString = "TwoStroke" + super.toString()
12 }
13 class FourStrokeEngine(hp: Int, state: Boolean, fl: FuelLevel)
14 extends Engine(hp, state, fl) {
15 override def toString = "FourStroke" + super.toString()
16 }
17
18 trait Make {def make: String}
19
20 class SteamEngine(hp: Int, state: Boolean, fl: FuelLevel, modelName: String)
21 extends Engine(hp, state, fl) with Make {
22 private val model = modelName
23 def this(hp: Int, state: Boolean, fl: FuelLevel) = this(hp, state, fl, "Toy")
24 def make = "SteamEngine - " + model
25 }
1 def main(args: Array[String]) {
2 val e1 = new FourStrokeEngine(40, false, FuelLevel.Empty)
3 println(e1)
4 e1.start // won't start
5 e1.fuelLevel = FuelLevel.Full
6 e1.start // will start: fuel-tank is now full
7 println(e1 + "\n")
8
9 val e2 = new TwoStrokeEngine(40, false, FuelLevel.Full)
10 println(e2)
11 e2.start
12 println(e2 + "\n")
13
14 val e3 = new SteamEngine(300, true, FuelLevel.Reserve)
15 println(e3)
16 println(e3.make + "\n")
17
18 val myengines = Array(e1, e2, e3)
19 println(myengines + "\n")
20 }
21 }
We covered:
Pros:
Cons:
Some popular software written in Scala: Apache Samza, Apache Kafka, Play! Framework, Lift Web Framework, Apache Spark Project, Scalding, Akka, ScalaNLP, Twitter Algebird, SummingBird and many more!
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |