Scala for Java Developers - Intro

132
Scala WTF is it? The new hotness or yet another functional fad? 1

description

Slides of a talk I gave at work on Scala. It is geared toward Java developers. Some of the examples are in my company's domain, which is analyzing energy usage (i.e. a "read" is an electric meter read).

Transcript of Scala for Java Developers - Intro

Page 1: Scala for Java Developers - Intro

ScalaWTF is it? The new hotness or yet another functional fad?

1

Page 2: Scala for Java Developers - Intro

Scalable LanguageThat’s why it’s pronounced Ska-Lah ?!??!

2

Page 3: Scala for Java Developers - Intro

Statically Typed

3

Page 4: Scala for Java Developers - Intro

Runs on the JVM

4

Page 5: Scala for Java Developers - Intro

Hybrid Language:Object-Oriented + Functional

5

Page 6: Scala for Java Developers - Intro

Why?

6

Page 7: Scala for Java Developers - Intro

Make Java more DRY

7

Page 8: Scala for Java Developers - Intro

Allow easy creation of DSLs

8

Page 9: Scala for Java Developers - Intro

Conciseness of Ruby +Safety of Static Typing

9

Page 10: Scala for Java Developers - Intro

No meta-programming but...very liberal syntax

10

Page 15: Scala for Java Developers - Intro

15

Page 17: Scala for Java Developers - Intro

Type Inference

17

Page 18: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();

18

Page 19: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String];

19

Page 20: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int

20

Page 21: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Intval doh = booyah / 3; // not a Float!!

21

Page 22: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Intval doh = booyah / 3; // not a Float!!val better:Float = booyah / 3;

22

Page 23: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Intval doh = booyah / 3; // not a Float!!val better:Float = booyah / 3;

// return type is java.lang.Stringdef fullName = { first + “,” + last; }

23

Page 24: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Intval doh = booyah / 3; // not a Float!!val better:Float = booyah / 3;

// return type is java.lang.Stringdef fullName = { first + “,” + last; }

If the type seems obvious to you...

24

Page 25: Scala for Java Developers - Intro

List<String> oyVey = new ArrayList<String>();var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Intval doh = booyah / 3; // not a Float!!val better:Float = booyah / 3;

// return type is java.lang.Stringdef fullName = { first + “,” + last; }

If the type seems obvious to you...Scala can usually figure it out, too

25

Page 26: Scala for Java Developers - Intro

Liberal Syntax

26

Page 27: Scala for Java Developers - Intro

val semicolons = “don’t need ‘em”val but = “if it’s not clear”; val you = “need them”

27

Page 28: Scala for Java Developers - Intro

val semicolons = “don’t need ‘em”val but = “if it’s not clear”; val you = “need them”

def braces(b:Boolean) = if (b) “needed for multiple expressions” else “you don’t need them”

28

Page 29: Scala for Java Developers - Intro

val semicolons = “don’t need ‘em”val but = “if it’s not clear”; val you = “need them”

def braces(b:Boolean) = if (b) “needed for multiple expressions” else “you don’t need them”

• if/else is a singular expression

29

Page 30: Scala for Java Developers - Intro

class Read(d:Date, val usage:Int) { def +(other:Int) = new Read(d,usage + other) override def toString = d + “:” + u

}

30

Page 31: Scala for Java Developers - Intro

class Read(d:Date, val usage:Int) { def +(other:Int) = new Read(d,usage + other) override def toString = d + “:” + u

}

val f = new Read(new Date,10)val g = f + 20

31

Page 32: Scala for Java Developers - Intro

class Read(d:Date, val usage:Int) { def +(other:Int) = new Read(d,usage + other) override def toString = d + “:” + u

}

val f = new Read(new Date,10)val g = f + 20val gee = f.+(20) // yuck, but legal

32

Page 33: Scala for Java Developers - Intro

class Read(d:Date, val usage:Int) { def +(other:Int) = new Read(d,usage + other) override def toString = d + “:” + u def later(ms:Int) = new Read(d + ms,usage)}

val f = new Read(new Date,10)val g = f + 20val gee = f.+(20) // yuck, but legalval l = f later (3600 * 1000)

33

Page 34: Scala for Java Developers - Intro

Mixins (Traits)

34

Page 35: Scala for Java Developers - Intro

abstract class SaneCompare[T] {  def <(other:T):Boolean  def >(other:T) = !(this < other)  def <=(other:T) = this == other || this < other  def >=(other:T) = this == other || this > other}class Read(d:Date,u:Int) extends SaneCompare[Read] {  val usage = u    def <(other:Read) = usage < other.usage }if (someRead >= someOtherRead) println(”finally!”)

35

Page 36: Scala for Java Developers - Intro

abstract class SaneCompare[T] {  def <(other:T):Boolean  def >(other:T) = !(this < other)  def <=(other:T) = this == other || this < other  def >=(other:T) = this == other || this > other}class Read(d:Date,u:Int) extends AbstractEntity {  val usage = u    def <(other:Read) = usage < other.usage }// hmmm....what now?

36

Page 37: Scala for Java Developers - Intro

abstract class SaneCompare[T] {  def <(other:T):Boolean  def >(other:T) = !(this < other)  def <=(other:T) = this == other || this < other  def >=(other:T) = this == other || this > other}class Read(d:Date,u:Int) extends AbstractEntity {  val usage = u    def <(other:Read) = usage < other.usage }// AbstractEntity extends SaneCompare?// God class above AbstractEntity subsumes it?

37

Page 38: Scala for Java Developers - Intro

abstract class SaneCompare[T] {  def <(other:T):Boolean  def >(other:T) = !(this < other)  def <=(other:T) = this == other || this < other  def >=(other:T) = this == other || this > other}class Read(d:Date,u:Int) extends AbstractEntity {  val usage = u    def <(other:Read) = usage < other.usage }// AbstractEntity extends SaneCompare?// God class above AbstractEntity subsumes it?// these are different concepts entirely

38

Page 39: Scala for Java Developers - Intro

trait SaneCompare[T] {  def <(other:T):Boolean  def >(other:T) = !(this < other)  def <=(other:T) = this == other || this < other  def >=(other:T) = this == other || this > other}class Read(d:Date,u:Int) extends AbstractEntity with SaneCompare[Read] {  val usage = u    def <(other:Read) = usage < other.usage }// now we have both!

39

Page 40: Scala for Java Developers - Intro

Traits

•Separate Concerns

40

Page 41: Scala for Java Developers - Intro

Traits

•Separate Concerns

•Precedence is based on declaration order

41

Page 42: Scala for Java Developers - Intro

Traits

•Separate Concerns

•Precedence is based on declaration order

•All abstract – just like Java interface

•None abstract – multiple inheritance

42

Page 43: Scala for Java Developers - Intro

Functions

43

Page 44: Scala for Java Developers - Intro

val reads = getSomeElectricReads // List[Read]

reads.sort( (a,b) => a.date.compareTo(b.date) < 0 )

44

Page 45: Scala for Java Developers - Intro

val reads = getSomeElectricReads // List[Read]

reads.sort( (a,b) => a.date.compareTo(b.date) < 0 )

45

Page 46: Scala for Java Developers - Intro

val reads = getSomeElectricReads // List[Read]

reads.sort( (a,b) => a.date.compareTo(b.date) < 0 )

def sort(compFunc:(Read,Read) => Boolean)

46

Page 47: Scala for Java Developers - Intro

val reads = getSomeElectricReads // List[Read]

reads.sort( (a,b) => a.date.compareTo(b.date) < 0 )

def sort(compFunc:(Read,Read) => Boolean)

Function2[Read,Read,Boolean]

47

Page 48: Scala for Java Developers - Intro

val reads = getSomeElectricReads // List[Read]

reads.sort( (a,b) => a.date.compareTo(b.date) < 0 )

def sort(compFunc:(Read,Read) => Boolean)

Function2[Read,Read,Boolean]

def sortReads(a:Read,b:Read) = a.date.compareTo(b.date) < 0

reads.sort(sortReads) // could also use a method // just keep in mind...

48

Page 49: Scala for Java Developers - Intro

Methods are not Functions

49

Page 50: Scala for Java Developers - Intro

Methods are not Functionsbut can be passed as Functions

50

Page 51: Scala for Java Developers - Intro

List Processing

51

Page 52: Scala for Java Developers - Intro

class State(val code:String,val desc:String)val states = getAllStates

// returns a List[String] with the codesstates.map( (state) => state.code )

// returns true if any state has a code of “DC”states.exists( (state) => state.code == “DC” )

// returns the state with the desc of “Hawaii”states.find( (state) => state.desc == “Hawaii” )

// returns a List[State] if states with descs matchingstates.filter( (state) => state.desc.startsWith(”V”) )

// Tons more

52

Page 53: Scala for Java Developers - Intro

Complete Access to JDK and Java libraries

53

Page 54: Scala for Java Developers - Intro

val s = new SingletonMetadataAwareAspectInstanceFactory()val foo = s.getOrderForAspectClass(classOf[FooBar])

54

Page 55: Scala for Java Developers - Intro

import java.util.Observerimport java.util.Observable

class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date)}

55

Page 56: Scala for Java Developers - Intro

import java.util.Observerimport java.util.Observable

class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date)}

56

Page 57: Scala for Java Developers - Intro

import java.util.Observerimport java.util.Observable

class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date)}

57

Page 58: Scala for Java Developers - Intro

import java.util.Observerimport java.util.Observable

class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date)}

58

Page 59: Scala for Java Developers - Intro

Goodbye Java’s Baggage

59

Page 60: Scala for Java Developers - Intro

No primitives

60

Page 61: Scala for Java Developers - Intro

Proper F’ing Propertiesclass ServicePoint(val id:String,var name:String)

val sp = new ServicePoint(”foo”,”The Foo House”)println(sp.id) // get, but no setprintln(sp.name)sp.name = “Thy Foo Haüs”

61

Page 62: Scala for Java Developers - Intro

Proper F’ing Propertiesclass ServicePoint(val id:String,private var _name:String) { def name = _name.toUpperCase def name_=(newName:String) = _name = newName}

val sp = new ServicePoint(”foo”,”The Foo House”)sp.name = “Thy Foo Haüs”println(sp.name) // prints THY FOO HAÜS

62

Page 63: Scala for Java Developers - Intro

¡Adiós Checked Exceptions!def readFile(f:File) = { val is = new FileInputStream(f) var ch = f.read while (ch != -1) { print(ch) ch = f.read }} // Wow, that was clean!

63

Page 64: Scala for Java Developers - Intro

¡Adiós Checked Exceptions!def readFile(f:File) = { try { val is = new FileInputStream(f) var ch = f.read() while (ch != -1) { print(ch) ch = f.read } } catch { case fnfe:FileNotFoundException => println(f + ” not found, dude: ” + fnfe) } // All others bubble out, even if checked in Java}

64

Page 65: Scala for Java Developers - Intro

Can I get a closure?class Logger(level:Int) { def debug(message: => String) = log(20,message) def info(message: => String) = log(10,message) def log(logLevel:Int, message: => String) = { if (level >= logLevel) println(message) }}val log = new Logger(10)log.debug(“Got read for “ + read.date + “ with usage “ + read.usage)read.usage = 44log.info(if read.usage < 10 “low read” else “high read”)

65

Page 66: Scala for Java Developers - Intro

Can I get a closure?class Logger(level:Int) { def debug(message: => String) = log(20,message) def info(message: => String) = log(10,message) def log(logLevel:Int, message: => String) = { if (level >= logLevel) println(message) }}val log = new Logger(10)log.debug(“Got read for “ + read.date + “ with usage “ + read.usage)read.usage = 44log.info(if read.usage < 10 “low read” else “high read”)

66

Page 67: Scala for Java Developers - Intro

Can I get a closure?class Logger(level:Int) { def debug(message: => String) = log(20,message) def info(message: => String) = log(10,message) def log(logLevel:Int, message: => String) = { if (level >= logLevel) println(message) }}val log = new Logger(10)log.debug(“Got read for “ + read.date + “ with usage “ + read.usage)read.usage = 44log.info(if read.usage < 10 “low read” else “high read”)

67

Page 68: Scala for Java Developers - Intro

Can I get a closure?class Logger(level:Int) { def debug(message: => String) = log(20,message) def info(message: => String) = log(10,message) def log(logLevel:Int, message: => String) = { if (level >= logLevel) println(message) }}val log = new Logger(10)log.debug(“Got read for “ + read.date + “ with usage “ + read.usage)read.usage = 44log.info(if read.usage < 10 “low read” else “high read”)

68

Page 69: Scala for Java Developers - Intro

Can I get a closure?class Logger(level:Int) { def debug(message: => String) = log(20,message) def info(message: => String) = log(10,message) def log(logLevel:Int, message: => String) = { if (level >= logLevel) println(message) }}val log = new Logger(10)log.debug(“Got read for “ + read.date + “ with usage “ + read.usage)read.usage = 44log.info(if read.usage < 10 “low read” else “high read”)

69

Page 70: Scala for Java Developers - Intro

“Literals”val triStateArea = List(”MD”,”DC”,”VA”)val theSouth = Map(”MD” -> true,”DC” -> false, ”VA” ->true)val perlCirca96 = (true,”Tuples rule”)val (hasTuples,message) = perlCirca96

70

Page 71: Scala for Java Developers - Intro

“Literals”val triStateArea = List(”MD”,”DC”,”VA”)val theSouth = Map(”MD” -> true,”DC” -> false, ”VA” ->true)val perlCirca96 = (true,”Tuples rule”)val (hasTuples,message) = perlCirca96

These are actually API calls

71

Page 72: Scala for Java Developers - Intro

“Literals”val triStateArea = List(”MD”,”DC”,”VA”)val theSouth = Map(”MD” -> true,”DC” -> false, ”VA” ->true)val perlCirca96 = (true,”Tuples rule”)val (hasTuples,message) = perlCirca96

This is done by the compilercreates a Tuple2[Boolean, String]

72

Page 73: Scala for Java Developers - Intro

“Literals”class Read(val id:Int, val usage:Int, val age:Int)

object Read { def apply(id:Int,usage:Int,age:Int) = new Read(id,usage,age)}

val read = Read(4,10,33)

73

Page 74: Scala for Java Developers - Intro

“Literals”class Read(val id:Int, val usage:Int, val age:Int)

object Read { def apply(id:Int,usage:Int,age:Int) = new Read(id,usage,age)}

val read = Read(4,10,33) // shortcut via compilerval read2 = Read.apply(4,10,33)

74

Page 75: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingdef fromEnglish(string:String) = string match { case “none” => 0 case “one” => 1 case _ => 2}

75

Page 76: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingdef toUML(obj:Any) = obj match { case 0 => “0” case 1 => “0..1” case n:Int => “0..” + n case true => “1” case false => “0” case “many” => “0..*” case _ => “0..*”}

76

Page 77: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingsealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

def proRate(read:Read) = read match { case AMIRead(d,usage,duration) => usage / duration case BillingRead(d,usage,days,c) => usage / days case CorrectedRead(BillingRead(d,oldUsage,days,c),usage) => (oldUsage + usage) / days}

77

Page 78: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingsealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

def proRate(read:Read) = read match { case AMIRead(d,usage,duration) => usage / duration case BillingRead(d,usage,days,c) => usage / days case CorrectedRead(BillingRead(d,oldUsage,days,c),usage) => (oldUsage + usage) / days}

• properties • equals/toString/hashCode• “extractor” • no need for “new”

78

Page 79: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingsealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

def proRate(read:Read) = read match { case AMIRead(d,usage,duration) => usage / duration case BillingRead(d,usage,days,c) => usage / days case CorrectedRead(BillingRead(d,oldUsage,days,c),usage) => (oldUsage + usage) / days}

79

Page 80: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingsealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

def proRate(read:Read) = read match { case AMIRead(d,usage,duration) => usage / duration case BillingRead(d,usage,days,c) => usage / days case CorrectedRead(BillingRead(d,oldUsage,days,c),usage) => (oldUsage + usage) / days}

80

Page 81: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingsealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

def proRate(read:Read) = read match { case AMIRead(d,usage,duration) => usage / duration case BillingRead(d,usage,days,c) => usage / days case CorrectedRead(BillingRead(d,oldUsage,days,c),usage) => (oldUsage + usage) / days}

81

Page 82: Scala for Java Developers - Intro

Crazy Awesome - Pattern Matchingsealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

def proRate(read:Read) = read match { case AMIRead(d,usage,duration) => usage / duration case BillingRead(d,usage,days,c) => usage / days case CorrectedRead(BillingRead(d,oldUsage,days,c),usage) => (oldUsage + usage) / days}

82

Page 83: Scala for Java Developers - Intro

Crazy Awesome - Implicitssealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

implicit def readToSeconds(r:Read):Int = r.date.getTime / 1000

def areConsecutive(from:Read, to:Read) = (from - to) <= from.duration

83

Page 84: Scala for Java Developers - Intro

Crazy Awesome - Implicitssealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

implicit def readToSeconds(r:Read):Int = r.date.getTime / 1000

def areConsecutive(from:Read, to:Read) = (from - to) <= from.duration

Have a Read, but need an Int

84

Page 85: Scala for Java Developers - Intro

Crazy Awesome - Implicitssealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

implicit def readToSeconds(r:Read):Int = r.date.getTime / 1000

def areConsecutive(from:Read, to:Read) = (from - to) > from.duration

Needs a Read and gives an Int

85

Page 86: Scala for Java Developers - Intro

Crazy Awesome - Implicitssealed abstract class Readcase class AMIRead(date:Date,usage:Int,duration:Int) extends Readcase class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Readcase class CorrectedRead(read:BillingRead, usage:Int) extends Read

implicit def readToSeconds(r:Read):Int = r.date.getTime / 1000

def areConsecutive(from:Read, to:Read) = (from - to) > from.duration

• Given this and matching, casting is rarely needed

86

Page 87: Scala for Java Developers - Intro

Crazy Awesome - XML Literalsval xml = <html> <head> <title>Scala Pronunciation Guide</title> </head> <body> <h1>How to Pronounce It</h1> </body></html>

println(xml)

87

Page 88: Scala for Java Developers - Intro

Crazy Awesome - XML Literalsval lang = getLangval title = translate(”scala.title”,lang)val xml = <html lang={lang}> <head> <title>{title}</title> </head> <body> <h1>{title.toUpperCase}</h1> </body></html>

println(xml)

88

Page 89: Scala for Java Developers - Intro

Crazy Awesome - XML Literalsval lang = getLangval title = translate(”scala.title”,lang)val xml = <html lang={lang}> <head> <title>{title}</title> </head> <body> <h1>{title.toUpperCase}</h1> </body></html>

println(xml)

89

Page 90: Scala for Java Developers - Intro

Crazy Awesome - XML Literalsval states = List(”DC”,”MD”,”VA”)val xml = <html> <body> <h1>States</h1> <ul> { states.map( (state) => <li>{state}</li> ) } </ul> </body></html>

println(xml)

90

Page 91: Scala for Java Developers - Intro

Concurrency

91

Page 92: Scala for Java Developers - Intro

Message-passing

92

Page 93: Scala for Java Developers - Intro

Message-passingimmutable objects

93

Page 94: Scala for Java Developers - Intro

Message PassingImmutable objects

“actors” with “mailboxes”

94

Page 95: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

95

Page 96: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

96

Page 97: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

97

Page 98: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

98

Page 99: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

99

Page 100: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

100

Page 101: Scala for Java Developers - Intro

case class Accumulate(amount: Int)case class Resetcase class Total

object Accumulator extends Actor { def act = { var sum = 0 loop { react { case Accumulate(n) => sum += n case Reset => sum = 0 case Total => reply(sum); exit } } }}

object Accumulators extends Application { Accumulator.start for(i <- (1 to 100)) { Accumulator ! Accumulate(i) } Accumulator !? Total match { case result: Int => println(result) }}

101

Page 102: Scala for Java Developers - Intro

There’s a lot more to it

102

Page 103: Scala for Java Developers - Intro

Demo

103

Page 104: Scala for Java Developers - Intro

DemoFill Gaps in Electric Meter Reads

104

Page 105: Scala for Java Developers - Intro

6/15 kwh

6/27 kwh

6/43 kwh

6/55 kwh

6/88 kwh

105

Page 106: Scala for Java Developers - Intro

6/15 kwh

6/27 kwh

6/43 kwh

6/55 kwh

6/88 kwh

6/3??

6/6??

6/7??

106

Page 107: Scala for Java Developers - Intro

for all consecutive reads r1 and r2 if r2 - r1 > one day fill gaps for (r1,r2)

107

Page 108: Scala for Java Developers - Intro

fill: for all reads (first,second,List(rest)) if gap(first,second) fill_gap(first,second) + fill(second + rest) else first + fill(second + rest)

108

Page 109: Scala for Java Developers - Intro

fill: for all reads (first,second,List(rest)) if !first || !second reads else if gap(first,second) fill_gap(first,second) + fill(second + rest) else first + fill(second + rest)

109

Page 110: Scala for Java Developers - Intro

def fillReads( strategy: (MeterRead,MeterRead) => Seq[MeterRead], reads:List[MeterRead]):List[MeterRead] =

reads match { case List() => List() case first :: List() => List(first) case first :: second :: rest if gap(first, second) => first :: strategy(x,y).toList ::: fillReads(strategy, second :: rest) case first :: rest => first :: fillReads(strategy,rest) }

110

Page 111: Scala for Java Developers - Intro

def fillReads( strategy: (MeterRead,MeterRead) => Seq[MeterRead], reads:List[MeterRead]):List[MeterRead] =

reads match { case List() => List() case first :: List() => List(first) case first :: second :: rest if gap(first, second) => first :: strategy(x,y).toList ::: fillReads(strategy, second :: rest) case first :: rest => first :: fillReads(strategy,rest) }

111

Page 112: Scala for Java Developers - Intro

def fillReads( strategy: (MeterRead,MeterRead) => Seq[MeterRead], reads:List[MeterRead]):List[MeterRead] =

reads match { case List() => List() case first :: List() => List(first) case first :: second :: rest if gap(first, second) => first :: strategy(x,y).toList ::: fillReads(strategy, second :: rest) case first :: rest => first :: fillReads(strategy,rest) }

112

Page 113: Scala for Java Developers - Intro

(demo with code)

113

Page 114: Scala for Java Developers - Intro

It’s all happy flowers and meadows?

114

Page 115: Scala for Java Developers - Intro

It’s all happy flowers and meadows?not quite; a few stumbling blocks

115

Page 116: Scala for Java Developers - Intro

Generics, type-variance, etc. can get really confusing at times

116

Page 117: Scala for Java Developers - Intro

Library docs not as extensive as Java’s

117

Page 118: Scala for Java Developers - Intro

Still have to compile

118

Page 119: Scala for Java Developers - Intro

Symbol Soup sometimes

119

Page 120: Scala for Java Developers - Intro

Symbol Soup sometimes...but it gets easier

120

Page 121: Scala for Java Developers - Intro

Static typing sometimes paints you into a (very dark and confusing) corner

121

Page 122: Scala for Java Developers - Intro

sometimes you just need method_missing

122

Page 123: Scala for Java Developers - Intro

sometimes you just needmonkey patching

123

Page 124: Scala for Java Developers - Intro

Where is Scala now?

124

Page 125: Scala for Java Developers - Intro

scala-lang.org

125

Page 126: Scala for Java Developers - Intro

mailing lists, irc, a few blogs

126

Page 127: Scala for Java Developers - Intro

One good book, a few others

127

Page 128: Scala for Java Developers - Intro

Online docs improving, but scattered

128

Page 129: Scala for Java Developers - Intro

Spec is surprisingly readable

129

Page 130: Scala for Java Developers - Intro

Java is on the decline

130

Page 131: Scala for Java Developers - Intro

Java is on the declineand Ruby and Python aren’t the

only options

131

Page 132: Scala for Java Developers - Intro

questions?

132