pragmatic real-world scala (short version)

108
Pragmatic Jonas Bonér Real-World Scala Scalable Solutions

Upload: jonas-boner

Post on 08-Sep-2014

44.293 views

Category:

Technology


0 download

DESCRIPTION

Short (45 min) version of my 'Pragmatic Real-World Scala' talk. Discussing patterns and idioms discovered during 1.5 years of building a production system for finance; portfolio management and simulation.

TRANSCRIPT

Page 1: Pragmatic Real-World Scala (short version)

Pragmatic

Jonas Bonér

Real-World Scala

Scalable Solutions

Page 2: Pragmatic Real-World Scala (short version)

“If I were to pick a language to use today other than Java, it would be Scala”

James Gosling

Page 3: Pragmatic Real-World Scala (short version)

Chat app in Lift Build a multi-user, comet-based chat app About 30 lines of code Three slides worth Slides By David Pollak, creator of Lift

Page 4: Pragmatic Real-World Scala (short version)

Define Messagescase class Add(who: Actor)

case class Remove(who: Actor)

case class Messages(msgs: List[String])

Page 5: Pragmatic Real-World Scala (short version)

Chat Server object ChatServer extends Actor { private var listeners: List[Actor] = Nil private var msgs: List[String] = Nil def act = loop { react { case s: String => msgs = s :: msgs listeners.foreach(l => l ! Messages(msgs)) case Add(who) => listeners = who :: listeners who ! Messages(msgs) case Remove(who) => listeners -= who } } this.start}

Page 6: Pragmatic Real-World Scala (short version)

Chat Comet Component class Chat extends CometActor {

private var msgs: List[String] = Nil def render = <div> <ul>{ msgs.reverse.map(m => <li>{ m }</li>) }</ul> { ajaxText("", s => { ChatServer ! s; Noop }) } </div> override def localSetup = ChatServer ! Add(this) override def localShutdown = ChatServer ! Remove(this) override def lowPriority = { case Messages(m) => msgs = m; reRender(false) }}

Page 7: Pragmatic Real-World Scala (short version)

Demo

Page 8: Pragmatic Real-World Scala (short version)

Scalable language

Page 9: Pragmatic Real-World Scala (short version)

Unique and elegant blend of

OO FP+

Page 10: Pragmatic Real-World Scala (short version)

Martin Odersky

Since 2003Sponsored by EPFL

Friendly and supportive

community

Runs on the JVM

Production ready

Pragmatic

Statically typed

Seamless Java interoperability

Page 11: Pragmatic Real-World Scala (short version)

Unique and elegant blend of

is...

Page 12: Pragmatic Real-World Scala (short version)

val phonebook = Map( “Jonas” -> “123456”, “Sara” -> “654321”)phonebook += (“Jacob” -> “987654”)println(phonebook(“Jonas”))

Expressive & light-weight

Page 13: Pragmatic Real-World Scala (short version)

High-level

boolean hasUpperCase = false;for (int i = 0; i < name.length(); i++) { if (Character.isUpperCase(name.charAt(i))) { hasUpperCase = true; break; }}

Java version

Page 14: Pragmatic Real-World Scala (short version)

High-level

val hasUpperCase = name.exists(_.isUpperCase)

Scala version

Page 15: Pragmatic Real-World Scala (short version)

// Javapublic 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(age: int) { this.age = age; }}

Concise

// Scalaclass Person( var name: String, var age: Int)

Page 16: Pragmatic Real-World Scala (short version)

Pure OO1 + 21.+(2)

123.toString()

Page 17: Pragmatic Real-World Scala (short version)

Extensibleval service = actor { loop { receive { case Add(x,y) => reply(x+y) case Sub(x,y) => reply(x-y) } }}service ! Add(4, 2) 6

Page 18: Pragmatic Real-World Scala (short version)

Pragmaticdef users = <users> <user role=”customer”> <name>{ user.name }</name> <password>{ user.password }</password> <email>{ user.email }</email> </user> ... </users>

Page 19: Pragmatic Real-World Scala (short version)

Pragmatic

users match { case <users>{users @ _*}</users> => for (user <- users) println(“User “ + (user \ “name”).text)}

Page 20: Pragmatic Real-World Scala (short version)

“direct:a“ ==> { loadbalance roundrobin { to (“mock:a“) to (“mock:b“) to (“mock:c“) }}

Great for DSLsApache Camel

Page 21: Pragmatic Real-World Scala (short version)

Scala isdeep

Page 22: Pragmatic Real-World Scala (short version)

But you don’t need to go very deep

to still have fun and be productive

Page 23: Pragmatic Real-World Scala (short version)

Java

Page 24: Pragmatic Real-World Scala (short version)

Tastier Java

Page 25: Pragmatic Real-World Scala (short version)

Different beast

Page 26: Pragmatic Real-World Scala (short version)

Composition

Page 27: Pragmatic Real-World Scala (short version)

in largeComposition

Page 28: Pragmatic Real-World Scala (short version)

building blocks

2

Page 29: Pragmatic Real-World Scala (short version)

TraitsSelf-type

&&

annotations

Page 30: Pragmatic Real-World Scala (short version)

Traittrait Dad { private var children: List[Child] = Nil

def addChild(child: Child) = children = child :: children

def getChildren = children.clone}

Page 31: Pragmatic Real-World Scala (short version)

Base

class Man(val name: String) extends Human

Page 32: Pragmatic Real-World Scala (short version)

Plumbing

Page 33: Pragmatic Real-World Scala (short version)

Static mixin composition

class Man(val name: String) extends Human with Dad

Page 34: Pragmatic Real-World Scala (short version)

Static mixin compositionusage

class Man(val name: String) extends Human with Dad

val jonas = new Man(“Jonas”)

)

jonas.addChild(new Child(“Jacob”))

Page 35: Pragmatic Real-World Scala (short version)

Dynamic mixin composition

val jonas = new Man(“Jonas”) with Dad

Page 36: Pragmatic Real-World Scala (short version)

jonas.addChild(new Child(“Jacob”))

Dynamic mixin compositionusage

val jonas = new Man(“Jonas”) with Dad

Page 37: Pragmatic Real-World Scala (short version)

3 different type of traits

Page 38: Pragmatic Real-World Scala (short version)

1

Page 39: Pragmatic Real-World Scala (short version)

Rich interfacetrait RichIterable[A] { def iterator: Iterator[A] // contract method

def foreach(f: A => Unit) = { val iter = iterator while (iter.hasNext) f(iter.next) }

def foldLeft[B](seed: B)(f: (B, A) => B) = { var result = seed foreach(e => result = f(result, e)) result }}

Page 40: Pragmatic Real-World Scala (short version)

val richSet = new java.util.HashSet[Int] with RichIterable[Int]

richSet.add(1)richSet.add(2)

richSet.foldLeft(0)((x, y) => x + y) 3

Rich interface

Page 41: Pragmatic Real-World Scala (short version)

2

Page 42: Pragmatic Real-World Scala (short version)

trait IgnoreCaseSet extends java.util.Set[String] {

abstract override def add(e: String) = { super.add(e.toLowerCase) } abstract override def contains(e: String) = { super.contains(e.toLowerCase) } abstract override def remove(e: String) = { super.remove(e.toLowerCase) }}

Stackable modifications

Page 43: Pragmatic Real-World Scala (short version)

val set = new java.util.HashSet[String] with IgnoreCaseSet

set.add(“HI THERE“) // uppercase

set.contains(“hi there“) // lowercase true

Stackable modifications

Page 44: Pragmatic Real-World Scala (short version)

trait LoggableSet extends java.util.Set[String] {

abstract override def add(e: String) = { println(“Add :“ + e) super.add(e) }

abstract override def remove(e: String) = { println(“Remove :“ + e) super.remove(e) }}

Add another trait interceptor

Page 45: Pragmatic Real-World Scala (short version)

val set = new java.util.HashSet[String] with IgnoreCaseSet with LoggableSet

set.add(“HI THERE“) “Add: HI THERE”

Run the stack of interceptors

Prints in uppercase

Page 46: Pragmatic Real-World Scala (short version)

val set = new java.util.HashSet[String] with LoggableSet with IgnoreCaseSet

set.add(“HI THERE“) “Add: hi there”

Change the order

Prints in lowercase

Page 47: Pragmatic Real-World Scala (short version)

3

Page 48: Pragmatic Real-World Scala (short version)

Trait Trait

Trait Trait

Trait

Multiple views

Base

Page 49: Pragmatic Real-World Scala (short version)

Trait Trait

Trait Trait

Trait

Base

Multiple views

Page 50: Pragmatic Real-World Scala (short version)

Traits

Multiplepersonalities

Page 51: Pragmatic Real-World Scala (short version)

Traits

Multiple

facets

Page 52: Pragmatic Real-World Scala (short version)

class Order(val cust: Customer)

Base

Page 53: Pragmatic Real-World Scala (short version)

Facetstrait Entity { ... }trait InventoryItemSet { ... }trait Invoicable { ... }trait PurchaseLimiter { ... }trait MailNotifier { ... }trait ACL { ... }trait Versioned { ... }trait Transactional { ... }

Page 54: Pragmatic Real-World Scala (short version)

val order = new Order(customer) with Entity with InventoryItemSet with Invoicable with PurchaseLimiter with MailNotifier with ACL with Versioned with Transactional

Composition

Page 55: Pragmatic Real-World Scala (short version)

What do you

need?

Page 56: Pragmatic Real-World Scala (short version)

DI

Page 57: Pragmatic Real-World Scala (short version)

this: <deps> =>

Page 58: Pragmatic Real-World Scala (short version)

this: <deps> =>

Page 59: Pragmatic Real-World Scala (short version)

Dependency declarationtrait UserService { this: UserRepository => ... // provided with composition userRepository.merge(user)}

…using self-type annotation

Page 60: Pragmatic Real-World Scala (short version)
Page 61: Pragmatic Real-World Scala (short version)

Duck typing

Page 62: Pragmatic Real-World Scala (short version)

if it walks like a duck…

and talks like a duck…

then it’s a duckDuck typing

Page 63: Pragmatic Real-World Scala (short version)

def authorize(target: { def getACL: ACL }) = { val acl = target.getACL ... //authorize}

Structural Typing: Duck-typing done right

Statically enforced

Page 64: Pragmatic Real-World Scala (short version)

in small

Composition

Page 65: Pragmatic Real-World Scala (short version)

“It's Time to Get Good at Functional Programming” Dr Dobb’s Journal Issue December 2008

Page 66: Pragmatic Real-World Scala (short version)

What’sall the

buzzabout?

Page 67: Pragmatic Real-World Scala (short version)

FPOrthogonal

Declarative

ReusableDeterministic

High-level

Referentiallytransparent

Immutable

Page 68: Pragmatic Real-World Scala (short version)

FP is like

Lego

Page 69: Pragmatic Real-World Scala (short version)

Small reusable pieces

with input

and output

Page 70: Pragmatic Real-World Scala (short version)

Unix pipes

cat File | grep 'println' | wc

Page 71: Pragmatic Real-World Scala (short version)

(x: Int) => x + 1

Functions

Page 72: Pragmatic Real-World Scala (short version)

Functions as valuesval inc = (x: Int) => x + 1

inc(1) 2

Page 73: Pragmatic Real-World Scala (short version)

Functions as parametershigh-order

List(1, 2, 3).map((x: Int) => x + 1) List(2, 3, 4)

Page 74: Pragmatic Real-World Scala (short version)

Functions as parameterswith sugar

List(1, 2, 3).map((x: Int) => x + 1)

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

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

Page 75: Pragmatic Real-World Scala (short version)

Functions as closures

val addMore = (x: Int) => x + more

Page 76: Pragmatic Real-World Scala (short version)

What is more?

Page 77: Pragmatic Real-World Scala (short version)

Some value outsidethe function’s lexical scopevar more = 7val addMore = (x: Int) => x + more

addMore(3) 10more = 8addMore(3) 11

Page 78: Pragmatic Real-World Scala (short version)

Data StructuresFunctional

Page 79: Pragmatic Real-World Scala (short version)

Immutable

Page 80: Pragmatic Real-World Scala (short version)

ListThe almighty

Page 81: Pragmatic Real-World Scala (short version)

ListsGrow at the frontInsert at front O(1)Insert at end O(n)

Page 82: Pragmatic Real-World Scala (short version)

List creation

List(1, 2, 3)

1 :: 2 :: 3 :: Nil

Page 83: Pragmatic Real-World Scala (short version)

Basics

val list = List(1, 2, 3)list.head 1list.tail List(2, 3)

list.isEmpty false

Page 84: Pragmatic Real-World Scala (short version)

High-level operationsval list = List(1, 2, 3)list.map(_ + 1) List(2, 3, 4)list.filter(_ < 2) List(3)list.exists(_ == 3) truelist.drop(2) List(3)list.reverse List(3, 2, 1)list.sort(_ > _) List(3, 2, 1)List.flatten(list) List(1, 2, 3)list.slice(2, 3) List(3)...

Page 85: Pragmatic Real-World Scala (short version)

115

functions defined on List

Page 86: Pragmatic Real-World Scala (short version)

Tuplesdef getNameAndAge: Tuple2[String, Int] = { val name = ... val age = ... (name, age)}

val (name, age) = getNameAndAgeprintln(“Name: “ + name)println(“Age: “ + age)

Page 87: Pragmatic Real-World Scala (short version)

Otherfunctional data structures:

MapsSets

TreesStacks

Page 88: Pragmatic Real-World Scala (short version)

for (n <- names) println(n)

For comprehensions

Page 89: Pragmatic Real-World Scala (short version)

for { att <- attendees if att.name == “Fred” lang <- att.spokenLanguages if lang == “Danish” } println(att)

Like SQL queries

Find all attendees named Fred that speaks Danish

Page 90: Pragmatic Real-World Scala (short version)

val companiesForAttendeesFromLondon = for { att <- attendees if att.address.city == “London” } yield att.company

for / yield

Page 91: Pragmatic Real-World Scala (short version)

for (thing <- thingsFromHere) yield getRealThing(thing)

Everything returns a value

Page 92: Pragmatic Real-World Scala (short version)

val things = for (thing <- thingsFromHere) yield getRealThing(thing)

Everything returns a value

Page 93: Pragmatic Real-World Scala (short version)

if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { ffor (thing <- thingsFromThere) yield thing }

Everything returns a value

Page 94: Pragmatic Real-World Scala (short version)

val things = if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { ffor (thing <- thingsFromThere) yield thing }

Everything returns a value

Page 95: Pragmatic Real-World Scala (short version)

try { if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { ffor (thing <- thingsFromThere) yield thing } } catch { case e => error(e); Nil }

Everything returns a value

Page 96: Pragmatic Real-World Scala (short version)

val things = try { if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { ffor (thing <- thingsFromThere) yield thing } } catch { case e => error(e); Nil }

Everything returns a value

Page 97: Pragmatic Real-World Scala (short version)

def getThingsFromSomewhere( fromHere: Boolean): List[Thing] = { try { if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { ffor (thing <- thingsFromThere) yield thing } } catch { case e => error(e); Nil }}

Everything returns a value

Page 98: Pragmatic Real-World Scala (short version)

Patternmatching

Page 99: Pragmatic Real-World Scala (short version)

def matchAny(a: Any): Any = a match { case 1 => “one” case “two” => 2 case i: Int => “scala.Int” case <tag>{ t }</tag> => t case head :: tail => head case _ => “default” }

Pattern matching

Page 100: Pragmatic Real-World Scala (short version)

Tools

Page 101: Pragmatic Real-World Scala (short version)

Tools: scala/binscala

scalacfsc

scaladocsbaz

Page 102: Pragmatic Real-World Scala (short version)

Tools: IDEsEclipse

NetBeansIntelliJ IDEA

EmacsJEdit

Page 103: Pragmatic Real-World Scala (short version)

BuildingMaven

AntSBT (Simple Build Tool )

Page 104: Pragmatic Real-World Scala (short version)

Tools: TestingSpecs

ScalaCheckScalaTest

SUnit

Page 105: Pragmatic Real-World Scala (short version)

Frameworks: WebLift

SweetSlinky

Pinky

Page 106: Pragmatic Real-World Scala (short version)

Learn more

[email protected]://jonasboner.com

http://scala-lang.org

Page 107: Pragmatic Real-World Scala (short version)

Professional help

http://scalablesolutions.se

Consulting Training Mentoring

Page 108: Pragmatic Real-World Scala (short version)

Pragmatic

Jonas Bonér

Real-World Scala

Scalable Solutions

Copyright 2009 Scalable Solutions