Top Banner
Introduction to Scala Aleksandar Prokopec EPFL
107

Introduction to Scala

Jul 06, 2015

Download

Software

Introduction to the basic features of the Scala programming language.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Introduction to Scala

Introduction to Scala

Aleksandar Prokopec

EPFL

Page 2: Introduction to Scala
Page 3: Introduction to Scala

Pragmatic

Since

2003

runs on the JVM

Seamless Java

interoperability

Statically typed

Production ready

Martin Odersky

Hybrid

Page 4: Introduction to Scala

Statically typed

Page 5: Introduction to Scala

runs on the JVM

Page 6: Introduction to Scala

Scala programs

are fast.

Page 7: Introduction to Scala

OOP + FP

Page 8: Introduction to Scala

“I can honestly say if someone had shown me the Programming

Scala book by Martin Odersky, Lex Spoon & Bill Venners back in

2003 I'd probably have never created Groovy.“

James Strachan, creator of Groovy

Page 9: Introduction to Scala

“If I were to pick a language to

use today other than Java, it

would be Scala.”

James Gosling

Page 10: Introduction to Scala

Pragmatic

Page 11: Introduction to Scala

Scala is lightweight.

Page 12: Introduction to Scala

println(“Hello world!”)

Page 13: Introduction to Scala

scala> println(“Hello world!”)

Hello world!

REPL evaluating expressions on the fly

Page 14: Introduction to Scala

object MyApp extends App {

println(“Hello world!”)

}

Compiled version

Page 15: Introduction to Scala

object MyApp extends App {

println(“Hello world!”)

}

Singleton objects no more static methods

Page 16: Introduction to Scala

object MyApp {

def main(args: Array[String]) {

println(“Hello world!”)

}

}

Declaring methods

Page 17: Introduction to Scala

object MyApp {

def main(args: Array[String]) {

var user: String = args(0)

println(“Hello, ”+user+“!”)

}

}

Declaring variables

Page 18: Introduction to Scala

object MyApp {

def main(args: Array[String]) {

val user: String = args(0)

println(“Hello, ”+user+“!”)

}

}

Declaring values prevents accidental changes

Page 19: Introduction to Scala

object MyApp {

def main(args: Array[String]) {

val user = args(0)

println(“Hello, ”+user+“!”)

}

}

Local type inference less… “typing”

Page 20: Introduction to Scala

class StringArrayFactory {

def create: Array[String] = {

val array: Array[String] =

Array[String](“1”, “2”, “3”)

array

}

}

Local type inference less… “typing”

Page 21: Introduction to Scala

class StringArrayFactory {

def create = {

val array = Array(“1”, “2”, “3”)

array

}

}

Local type inference less… “typing”

Page 22: Introduction to Scala

// Scala

class Person(

var name: String,

var age: Int

)

Declaring classes …concisely

// Java

public class Person {

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public int getAge() {

return age;

}

public void setName(String name) {

this.name = name;

}

public void setAge(int age) {

this.age = age;

}

}

Page 23: Introduction to Scala

Scala is object-oriented.

Page 24: Introduction to Scala

object Foo {

val b = new ArrayBuffer[Any]

}

Object-oriented everything’s an object

Page 25: Introduction to Scala

Object-oriented everything’s an object

Any

AnyRef AnyVal

String

Boolean

Char

Int

Page 26: Introduction to Scala

object Foo {

val b = new ArrayBuffer[Any]

b += 1

b += 1.toString

b += Foo

println(b)

}

Object-oriented everything’s an object

Page 27: Introduction to Scala

1 + 2

1.+(2)

Array(1, 2, 3) ++ Array(4, 5, 6)

Array(1, 2, 3).++(Array(4, 5, 6))

1 :: List(2, 3)

List(2, 3).::(1)

Operator overloading operators are methods

Page 28: Introduction to Scala

trait Iterator[T] {

def next(): T

def hasNext: Boolean

}

Declaring traits traits are like interfaces

Page 29: Introduction to Scala

trait Iterator[T] {

def next(): T

def hasNext: Boolean

def printAll() =

while (hasNext) println(next())

}

Declaring traits traits are rich

Page 30: Introduction to Scala

trait Animal

Multiple inheritance traits are composable

Page 31: Introduction to Scala

trait Animal

trait Mammal extends Animal {

def think() = println(“hm...”)

}

Multiple inheritance traits are composable

Page 32: Introduction to Scala

trait Animal

trait Mammal extends Animal {

def think() = println(“hm...”)

}

trait Bird extends Animal {

def layEgg() = System.createEgg()

}

Multiple inheritance traits are composable

Page 33: Introduction to Scala
Page 34: Introduction to Scala

trait Animal

trait Mammal extends Animal {

def think() = println(“hm...”)

}

trait Bird extends Animal {

def layEgg() = System.createEgg()

}

class Platypus extends Bird with Mammal

Mixin composition traits are composable

Page 35: Introduction to Scala

trait Animal

trait Reptile extends Animal {

def layInTheSun: Unit = {}

}

class Dog(name: String) extends Mammal

new Dog(“Nera”) with Reptile

Dynamic mixin composition …or composition “on the fly”

Page 36: Introduction to Scala

Cake pattern

Page 37: Introduction to Scala

trait Logging {

def log(msg: String)

}

trait AnsweringMachine {

self: Logging with DAO with Protocol =>

log(“Initializing.”)

...

}

Self-types to express requirements

Page 38: Introduction to Scala

trait ConsoleLogging {

def log(msg: String) = println(msg)

}

class LocalAnsweringMachine

extends AnsweringMachine

with ConsoleLogging

with H2DAO

with JabberProtocol

Cake pattern layers above layers

Page 39: Introduction to Scala

Scala is functional.

Page 40: Introduction to Scala

(x: Int) => x + 1

First class functions

Page 41: Introduction to Scala

val doub: Int => Int = (x: Int) => x * 2

doub(1)

2

First class functions functions are objects too

Page 42: Introduction to Scala

val doub = (x: Int) => x * 2

List(1, 2, 3).map(doub)

List(2, 4, 6)

First class functions as higher order parameters

Page 43: Introduction to Scala

List[Int](1, 2, 3).map((x: Int) => x * 2)

// more type inference

List(1, 2, 3).map(x => x * 2)

// or even shorter

List(1, 2, 3).map(_ * 2)

Functions with sugar make code sweeter

Page 44: Introduction to Scala

var step = 1

val inc = x => x + step

inc(5)

6

step = 2

inc(5)

7

Closures functions that “capture” their environment

Page 45: Introduction to Scala

// Java

button.addMouseListener(new MouseAdapter() {

public void mouseEntered(MouseEvent e) {

System.out.println(e);

}

}

// Scala

listenTo(button)

reactions += { case e => println(e) }

First class functions because you write them in Java all the time

Page 46: Introduction to Scala

Pattern matching

Page 47: Introduction to Scala

Pattern matching …is concise

// Scala

reactions += {

case m: MouseEntered =>

println(“I see it!”)

case m: MouseExited =>

println(“Lost it.”)

case m: MouseClicked =>

println(“Poked!”)

}

// Java

button.addMouseListener(new MouseAdapter() {

public void mousePressed(MouseEvent e) {}

public void mouseReleased(MouseEvent e) {}

public void mouseEntered(MouseEvent e) {}

public void mouseEntered(MouseEvent e) {

System.out.println(“I see it!”);

}

public void mouseExited(MouseEvent e) {

System.out.println(“Lost it.”);

}

public void mouseClicked(MouseEvent e) {

System.out.println(“Poked!”);

}

}

// ...alternative - isinstanceof

Page 48: Introduction to Scala

trait Tree

case class Node(l: Tree, r: Tree)

extends Tree

case object Leaf

extends Tree

Pattern matching …is precise

Page 49: Introduction to Scala

def b(t: Tree): Int = t match {

case Node(Leaf, Node(_, _)) |

Node(Node(_, _), Leaf) => -1

case Node(l, r) =>

val (ld, rd) = (b(l), b(r))

if (ld == rd) ld + 1 else -1

case Leaf => 0

case _ => error(“Unknown tree!”)

}

Pattern matching …is precise

Page 50: Introduction to Scala

sealed trait Tree

...

def b(t: Tree): Int = t match {

case Node(Leaf, Node(_, _)) |

Node(Node(_, _), Leaf) => -1

case Node(l, r) =>

val (ld, rd) = (b(l), b(r))

if (ld == rd) ld + 1 else -1

case Leaf => 0

}

Pattern matching …is exhaustive

Page 51: Introduction to Scala

def matchingMeSoftly(a: Any): Any =

a match {

case 11 => “eleven”

case s: String => “’%s’”.format(s)

case <tag>{t}</tag> => t

case Array(1, 2, 3) => “1, 2, 3”

case head :: tail => tail

case _ => null

}

Pattern matching …is extensible

Page 52: Introduction to Scala

Lazyness

Page 53: Introduction to Scala

lazy values don’t compute if there’s no demand

class User(id: Int) {

lazy val followernum =

from(followers)(f =>

where(id === f.fid)

compute(countDistinct(f.fid))

)

}

Page 54: Introduction to Scala

Call by name evaluate only when you have to

def withErrorOut(body: =>Unit) = {

val old = Console.out

Console.setOut(Console.err)

try body

finally Console.setOut(old)

}

...

withErrorOut {

if (n < 0) println(“n too small”)

}

Page 55: Introduction to Scala

Streams lazy lists

e = ∑ 1/n!

= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …

Page 56: Introduction to Scala

Streams lazy lists

e = ∑ 1/n!

= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …

0! ?

Page 57: Introduction to Scala

Streams lazy lists

e = ∑ 1/n!

= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …

0! 1! 2! 3! ?

0! ?

Page 58: Introduction to Scala

Streams lazy lists

e = ∑ 1/n!

= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …

0! 1! 2! 3! ?

0! ?

0! 1/1! 1/2! 1/3! ?

Page 59: Introduction to Scala

Streams lazy lists

def fact(n: Int, p: Int): Stream[Int] =

p #:: fact(n + 1, p * (n + 1))

val factorials = fact(0, 1)

val e = factorials.map(1./_).take(10).sum

Page 60: Introduction to Scala

Scala is expressive.

Page 61: Introduction to Scala

for comprehensions traverse anything

for (x <- List(1, 2, 3)) println(x)

List(1, 2, 3).foreach(x => println(x))

for (x <- 0 until 10) println(x)

(0 until 10).foreach(x => println(x))

Range(0, 10, 1).foreach(x => println(x))

Page 62: Introduction to Scala

for comprehensions map anything

for (x <- List(1, 2, 3)) yield x * 2

List(1, 2, 3).map(x => x * 2)

for (x <- List(1, 2); y <- List(1, 2))

yield x * y

List(1, 2).flatMap(x =>

List(1, 2).map(y => x * y)

)

List(1, 2, 2, 4)

Page 63: Introduction to Scala

for comprehensions like SQL queries

for {

p <- people

if p.age > 25

s <- schools

if p.degree == s.degree

} yield (p, s)

// pairs of people older than 25 and

// schools they possibly attended

Page 64: Introduction to Scala

Collections easy to create

val phonebook = Map(

“Jean” -> “123456”,

“Damien” -> “666666”)

val meetings = ArrayBuffer(

“Dante”, “Damien”, “Sophie”)

println(phonebook(meetings(1)))

Page 65: Introduction to Scala

Collections high-level combinators

// Java

boolean isOk = true

for (int i = 0; i < name.length(); i++) {

if (isLetterOrDigit(name.charAt(i)) {

isOk = false;

break;

}

}

Page 66: Introduction to Scala

Collections high-level combinators

// Scala

name.forall(_.isLetterOrDigit)

Page 67: Introduction to Scala

Collections high-level combinators

// count the total number of different

// surnames shared by at least 2 adults

people

Page 68: Introduction to Scala

Collections high-level combinators

// count the total number of different

// surnames shared by at least 2 adults

people.filter(_.age >= 18)

Page 69: Introduction to Scala

Collections high-level combinators

// count the total number of different

// surnames shared by at least 2 adults

people.filter(_.age >= 18)

.groupBy(_.surname): Map[String, List[Person]]

Page 70: Introduction to Scala

Collections high-level combinators

// count the total number of different

// surnames shared by at least 2 adults

people.filter(_.age >= 18)

.groupBy(_.surname): Map[String, List[Person]]

.count { case (s, l) => l.size >= 2 }

Page 71: Introduction to Scala

Lists an immutable sequence

val countdown = List(3, 2, 1)

3 2 1

countdown

Page 72: Introduction to Scala

Lists an immutable sequence

val countdown = List(3, 2, 1)

val longer = 4 :: countdown

3 2 1 4

countdown

longer

Page 73: Introduction to Scala

Lists an immutable sequence

val countdown = List(3, 2, 1)

val longer = 4 :: countdown

val fast = 10 :: countdown

3 2 1 4

10

countdown

longer

fast

Page 74: Introduction to Scala

Lists an immutable sequence

val countdown = List(3, 2, 1)

val longer = 4 :: countdown

val fast = 10 :: countdown

val withzero = countdown ::: List(0)

3 2 1 4

10

3 2 1 0

countdown

longer

fast

withzero

Page 75: Introduction to Scala

Buffers mutable sequences

val b = ArrayBuffer(1, 2, 3)

b += 4

b += 5

b += 6

ArrayBuffer(1, 2, 3, 4, 5, 6)

Page 76: Introduction to Scala

Maps mutable or immutable, sorted or unsorted

import collection._

val m = mutable.Map(“Heidfeld” -> 1,

“Schumacher” -> 2)

m += “Hakkinen” -> 3

val im = immutable.Map(“Schumacher” -> 1)

Page 77: Introduction to Scala

Hash tries persistence through efficient structural sharing

val im0: Map[Int, Int] = ...

im0

Page 78: Introduction to Scala

Hash tries persistence through efficient structural sharing

val im0: Map[Int, Int] = ...

val im1 = im0 + (1 -> 1)

im0 im1

Page 79: Introduction to Scala

Hash tries persistence through efficient structural sharing

val im0: Map[Int, Int] = ...

val im1 = im0 + (1 -> 1)

val im2 = im1 + (2 -> 2)

im0 im1 im2

Page 80: Introduction to Scala

Hash tries persistence through efficient structural sharing

val im0: Map[Int, Int] = ...

val im1 = im0 + (1 -> 1)

val im2 = im1 + (2 -> 2)

val im3 = im2 + (3 -> 6)

im0 im1 im2 im3

Page 81: Introduction to Scala

Hash tries persistence through efficient structural sharing

im0 im1 im2 im3

2x-3x slower lookup

2x faster iteration

Page 82: Introduction to Scala

Parallel collections parallelize bulk operations on collections

def cntEqlen(m: Map[String, String]) = {

m.par.count {

case (n, s) => n.length == s.length

}

}

// be careful with side-effects

Page 83: Introduction to Scala

Scala is extensible.

Page 84: Introduction to Scala

One ring to rule them all.

Page 85: Introduction to Scala

actors road to safer concurrency

val a = actor {

react {

case i: Int => println(i)

}

}

...

a ! 5

Page 86: Introduction to Scala

Custom control flow it’s all about control

def myWhile(c: =>Boolean)(b: =>Unit) {

if (c) {

b

myWhile(c)(b)

}

}

Page 87: Introduction to Scala

Custom control flow it’s all about control

@tailrec

def myWhile(c: =>Boolean)(b: =>Unit) {

if (c) {

b

myWhile(c)(b)

}

}

Page 88: Introduction to Scala

Custom control flow it’s all about control

@tailrec

def myWhile(c: =>Boolean)(b: =>Unit) {

if (c) {

b

myWhile(c)(b)

}

}

var i = 0

myWhile (i < 5) {

i += 1

}

Page 89: Introduction to Scala

ARM automatic resource management

withFile (“~/.bashrc”) { f =>

for (l <- f.lines) {

if (“#”.r.findFirstIn(l) != None)

println(l)

}

}

Page 90: Introduction to Scala

ScalaTest behavioral testing framework

“A list” should {

“be a double reverse of itself” in {

val ls = List(1, 2, 3, 4, 5, 6)

ls.reverse.reverse should equal (ls)

}

}

Page 91: Introduction to Scala

BaySick Basic DSL in Scala

10 PRINT “Baysick Lunar Lander v0.9”

20 LET ('dist := 100)

30 LET ('v := 1)

40 LET ('fuel := 1000)

50 LET ('mass := 1000)

...

Page 92: Introduction to Scala

implicit conversions augmenting types with new operations

‘a’.toUpperCase

Page 93: Introduction to Scala

implicit conversions augmenting types with new operations

implicit def charOps(c: Char) = new {

def toUpperCase =

if (c >= ‘a’ && c <= ‘z’)

(c – 32).toChar

else c

}

...

‘a’.toUpperCase

Page 94: Introduction to Scala

Pimp my library

Page 95: Introduction to Scala

implicit conversions pimping your libraries since 2006

import scalaj.collection._

val list = new java.util.ArrayList[Int]

list.add(1)

list.add(2)

list.add(3)

...

for (x <- list) yield x * 2

Page 96: Introduction to Scala

implicit conversions pimping your libraries since 2006

import scalaj.collection._

val list = new java.util.ArrayList[Int]

list.add(1)

list.add(2)

list.add(3)

...

for (x <- list) yield x * 2

// list.map(x => x * 2)

Page 97: Introduction to Scala

implicit conversions pimping your libraries since 2006

import scalaj.collection._

val list = new java.util.ArrayList[Int]

list.add(1)

list.add(2)

list.add(3)

...

for (x <- list) yield x * 2

// jlist2slist(list).map(x => x * 2)

Page 98: Introduction to Scala

implicit arguments restricting operations on types

val is = SortedSet(1, 2, 3)

case class Man(id: Int)

...

implicit object MenOrd extends Ordering[Man] {

def compare(x: Man, y: Man) = x.id – y.id

}

val ms = SortedSet(Person(1), Person(2))

Page 99: Introduction to Scala

STM software transactional memory

val account1 = cell[Int]

val account2 = cell[Int]

atomic { implicit txn =>

if (account2() >= 50) {

account1 += 50

account2 -= 50

}

}

Page 100: Introduction to Scala

Scala has support.

Page 101: Introduction to Scala

Building

Ant

SBT

Maven

Page 102: Introduction to Scala

SBT simple build tool

> compile

...

> ~compile

...

> test

...

> package

Page 103: Introduction to Scala

SBT project definition written in Scala

val scalatest =

“org.scala-tools.testing” %

“scalatest” % “0.9.5”

...

> reload

[INFO] Building project ...

[INFO] using sbt.Default ...

> update

Page 104: Introduction to Scala

Tools: IDEs

Eclipse

Netbeans

IntelliJ IDEA

Emacs

ENSIME

JEdit

Page 105: Introduction to Scala

Web frameworks

Page 106: Introduction to Scala

Used by...

Page 107: Introduction to Scala

Thank you!