introduction to scala

107
Introduction to Scala Aleksandar Prokopec EPFL

Upload: aleksandar-prokopec

Post on 06-Jul-2015

368 views

Category:

Software


1 download

DESCRIPTION

Introduction to the basic features of the Scala programming language.

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!