SlideShare una empresa de Scribd logo
1 de 132
Descargar para leer sin conexión
Scala
WTF is it? The new hotness or yet another functional fad?




                                                            1
Scalable Language
 That’s why it’s pronounced Ska-Lah ?!??!




                                            2
Statically Typed



                   3
Runs on the JVM



                  4
Hybrid Language:
Object-Oriented + Functional


                               5
Why?



       6
Make Java more DRY



                     7
Allow easy creation of DSLs



                              8
Conciseness of Ruby +
Safety of Static Typing


                          9
No meta-programming but...
    very liberal syntax


                             10
11
12
13
14
15
16
Type Inference



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




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




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




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




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




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

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




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

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

If the type seems obvious to you...


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

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

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

                                                25
Liberal Syntax



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




                                                       27
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
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
class Read(d:Date, val usage:Int) {
  def +(other:Int) = new Read(d,usage + other)
  override def toString = d + “:” + u

}




                                                 30
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
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
val gee = f.+(20) // yuck, but legal




                                                 32
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 + 20
val   gee   = f.+(20) // yuck, but legal
val   l =   f later (3600 * 1000)




                                                 33
Mixins (Traits)



                  34
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
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
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
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
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
Traits



•   Separate Concerns



                           40
Traits


•Separate Concerns
• Precedence is based on declaration order


                                             41
Traits

•Separate Concerns
• Precedence is based on declaration order
• All abstract – just like Java interface
• None abstract – multiple inheritance

                                             42
Functions



            43
val reads = getSomeElectricReads // List[Read]

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




                                                      44
val reads = getSomeElectricReads // List[Read]

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




                                                      45
val reads = getSomeElectricReads // List[Read]

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


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




                                                      46
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
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
Methods are not Functions




                            49
Methods are not Functions
but can be passed as Functions


                                 50
List Processing



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

// returns a List[String] with the codes
states.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 matching
states.filter( (state) => state.desc.startsWith(”V”) )

// Tons more


                                                         52
Complete Access to JDK and Java
           libraries


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




                                                            54
import java.util.Observer
import java.util.Observable

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




                                                  55
import java.util.Observer
import java.util.Observable

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




                                                  56
import java.util.Observer
import java.util.Observable

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




                                                  57
import java.util.Observer
import java.util.Observable

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




                                                  58
Goodbye Java’s Baggage



                         59
No primitives




                60
Proper F’ing Properties
class ServicePoint(val id:String,var name:String)

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




                                                    61
Proper F’ing Properties
class 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
¡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
¡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
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 = 44
log.info(if read.usage < 10 “low read”
  else “high read”)

                                                    65
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 = 44
log.info(if read.usage < 10 “low read”
  else “high read”)

                                                    66
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 = 44
log.info(if read.usage < 10 “low read”
  else “high read”)

                                                    67
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 = 44
log.info(if read.usage < 10 “low read”
  else “high read”)

                                                    68
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 = 44
log.info(if read.usage < 10 “low read”
  else “high read”)

                                                    69
“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
“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
“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 compiler
     creates a Tuple2[Boolean, String]

                                                 72
“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
“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 compiler
val read2 = Read.apply(4,10,33)




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




                                                  75
Crazy Awesome - Pattern Matching
def 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
Crazy Awesome - Pattern Matching
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Pattern Matching
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Pattern Matching
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Pattern Matching
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Pattern Matching
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Pattern Matching
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Implicits
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Implicits
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Implicits
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - Implicits
sealed abstract class Read
case class AMIRead(date:Date,usage:Int,duration:Int) extends Read
case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read
case 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
Crazy Awesome - XML Literals
val xml = <html>
  <head>
    <title>Scala Pronunciation Guide</title>
  </head>
  <body>
    <h1>How to Pronounce It</h1>
  </body>
</html>

println(xml)




                                               87
Crazy Awesome - XML Literals
val lang = getLang
val 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
Crazy Awesome - XML Literals
val lang = getLang
val 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
Crazy Awesome - XML Literals
val 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
Concurrency



              91
Message-passing




                  92
Message-passing
immutable objects



                    93
Message Passing
    Immutable objects
“actors” with “mailboxes”


                            94
case class Accumulate(amount: Int)
case class Reset
case 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
case class Accumulate(amount: Int)
case class Reset
case 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
case class Accumulate(amount: Int)
case class Reset
case 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
case class Accumulate(amount: Int)
case class Reset
case 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
case class Accumulate(amount: Int)
case class Reset
case 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
case class Accumulate(amount: Int)
case class Reset
case 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
case class Accumulate(amount: Int)
case class Reset
case 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
There’s a lot more to it



                           102
Demo




       103
Demo
Fill Gaps in Electric Meter Reads


                                    104
6/1     6/2     6/4     6/5     6/8
5 kwh   7 kwh   3 kwh   5 kwh   8 kwh




                                        105
6/1     6/2           6/4     6/5                 6/8
5 kwh   7 kwh         3 kwh   5 kwh               8 kwh
                6/3                   6/6   6/7
                 ??                    ??    ??




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




                                      107
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
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
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
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
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
(demo with code)



                   113
It’s all happy flowers and meadows?




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



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


                                    116
Library docs not as extensive as
             Java’s


                                   117
Still have to compile



                        118
Symbol Soup sometimes




                        119
Symbol Soup sometimes
  ...but it gets easier


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



                                          121
sometimes you just need
   method_missing



                          122
sometimes you just need
   monkey patching


                          123
Where is Scala now?



                      124
scala-lang.org



                 125
mailing lists, irc, a few blogs



                                  126
One good book, a few others



                              127
Online docs improving, but
        scattered


                             128
Spec is surprisingly readable



                                129
Java is on the decline




                         130
Java is on the decline
and Ruby and Python aren’t the
          only options


                                 131
questions?



             132

Más contenido relacionado

La actualidad más candente

ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うbpstudy
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Jesper Kamstrup Linnet
 
Operator Overloading In Scala
Operator Overloading In ScalaOperator Overloading In Scala
Operator Overloading In ScalaJoey Gibson
 
Generics and Lambda survival guide - DevNexus 2017
Generics and Lambda survival guide - DevNexus 2017Generics and Lambda survival guide - DevNexus 2017
Generics and Lambda survival guide - DevNexus 2017Henri Tremblay
 
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...scalaconfjp
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with ScalaDenis
 
Scala for ruby programmers
Scala for ruby programmersScala for ruby programmers
Scala for ruby programmerstymon Tobolski
 
The Ring programming language version 1.6 book - Part 37 of 189
The Ring programming language version 1.6 book - Part 37 of 189The Ring programming language version 1.6 book - Part 37 of 189
The Ring programming language version 1.6 book - Part 37 of 189Mahmoud Samir Fayed
 
Scala-对Java的修正和超越
Scala-对Java的修正和超越Scala-对Java的修正和超越
Scala-对Java的修正和超越Caoyuan Deng
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecLoïc Descotte
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java DevelopersMichael Galpin
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and ClosuresSandip Kumar
 
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Sanjeev_Knoldus
 

La actualidad más candente (20)

ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使う
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
 
Operator Overloading In Scala
Operator Overloading In ScalaOperator Overloading In Scala
Operator Overloading In Scala
 
Java string handling
Java string handlingJava string handling
Java string handling
 
Generics and Lambda survival guide - DevNexus 2017
Generics and Lambda survival guide - DevNexus 2017Generics and Lambda survival guide - DevNexus 2017
Generics and Lambda survival guide - DevNexus 2017
 
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
 
Workshop Scala
Workshop ScalaWorkshop Scala
Workshop Scala
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with Scala
 
Scala for ruby programmers
Scala for ruby programmersScala for ruby programmers
Scala for ruby programmers
 
The Ring programming language version 1.6 book - Part 37 of 189
The Ring programming language version 1.6 book - Part 37 of 189The Ring programming language version 1.6 book - Part 37 of 189
The Ring programming language version 1.6 book - Part 37 of 189
 
Scala-对Java的修正和超越
Scala-对Java的修正和超越Scala-对Java的修正和超越
Scala-对Java的修正和超越
 
Why Haskell
Why HaskellWhy Haskell
Why Haskell
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar Prokopec
 
A bit about Scala
A bit about ScalaA bit about Scala
A bit about Scala
 
Scala
ScalaScala
Scala
 
Scala for Jedi
Scala for JediScala for Jedi
Scala for Jedi
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java Developers
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
 
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
 

Similar a Scala for Java Developers - Intro

(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Scala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian DragosScala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian Dragos3Pillar Global
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scaladjspiewak
 
2.1 recap from-day_one
2.1 recap from-day_one2.1 recap from-day_one
2.1 recap from-day_onefuturespective
 
Lambda functions in java 8
Lambda functions in java 8Lambda functions in java 8
Lambda functions in java 8James Brown
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksSeniorDevOnly
 
TI1220 Lecture 8: Traits & Type Parameterization
TI1220 Lecture 8: Traits & Type ParameterizationTI1220 Lecture 8: Traits & Type Parameterization
TI1220 Lecture 8: Traits & Type ParameterizationEelco Visser
 
Scala collections api expressivity and brevity upgrade from java
Scala collections api  expressivity and brevity upgrade from javaScala collections api  expressivity and brevity upgrade from java
Scala collections api expressivity and brevity upgrade from javaIndicThreads
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 

Similar a Scala for Java Developers - Intro (20)

(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
ScalaBlitz
ScalaBlitzScalaBlitz
ScalaBlitz
 
Scala for curious
Scala for curiousScala for curious
Scala for curious
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Scala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian DragosScala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian Dragos
 
Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
Scala
ScalaScala
Scala
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scala
 
2.1 recap from-day_one
2.1 recap from-day_one2.1 recap from-day_one
2.1 recap from-day_one
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat Sheet
 
Lambda functions in java 8
Lambda functions in java 8Lambda functions in java 8
Lambda functions in java 8
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
 
TI1220 Lecture 8: Traits & Type Parameterization
TI1220 Lecture 8: Traits & Type ParameterizationTI1220 Lecture 8: Traits & Type Parameterization
TI1220 Lecture 8: Traits & Type Parameterization
 
Scala collections api expressivity and brevity upgrade from java
Scala collections api  expressivity and brevity upgrade from javaScala collections api  expressivity and brevity upgrade from java
Scala collections api expressivity and brevity upgrade from java
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 

Último

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 

Último (20)

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 

Scala for Java Developers - Intro

  • 1. Scala WTF is it? The new hotness or yet another functional fad? 1
  • 2. Scalable Language That’s why it’s pronounced Ska-Lah ?!??! 2
  • 4. Runs on the JVM 4
  • 6. Why? 6
  • 9. Conciseness of Ruby + Safety of Static Typing 9
  • 10. No meta-programming but... very liberal syntax 10
  • 11. 11
  • 12. 12
  • 13. 13
  • 14. 14
  • 15. 15
  • 16. 16
  • 18. List<String> oyVey = new ArrayList<String>(); 18
  • 19. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; 19
  • 20. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int 20
  • 21. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int val doh = booyah / 3; // not a Float!! 21
  • 22. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int val doh = booyah / 3; // not a Float!! val better:Float = booyah / 3; 22
  • 23. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int val doh = booyah / 3; // not a Float!! val better:Float = booyah / 3; // return type is java.lang.String def fullName = { first + “,” + last; } 23
  • 24. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int val doh = booyah / 3; // not a Float!! val better:Float = booyah / 3; // return type is java.lang.String def fullName = { first + “,” + last; } If the type seems obvious to you... 24
  • 25. List<String> oyVey = new ArrayList<String>(); var hellsYeah = new ArrayList[String]; val booyah = 45; // it’s an Int val doh = booyah / 3; // not a Float!! val better:Float = booyah / 3; // return type is java.lang.String def fullName = { first + “,” + last; } If the type seems obvious to you... Scala can usually figure it out, too 25
  • 27. val semicolons = “don’t need ‘em” val but = “if it’s not clear”; val you = “need them” 27
  • 28. 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
  • 29. 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
  • 30. class Read(d:Date, val usage:Int) { def +(other:Int) = new Read(d,usage + other) override def toString = d + “:” + u } 30
  • 31. 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
  • 32. 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 val gee = f.+(20) // yuck, but legal 32
  • 33. 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 + 20 val gee = f.+(20) // yuck, but legal val l = f later (3600 * 1000) 33
  • 35. 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
  • 36. 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
  • 37. 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
  • 38. 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
  • 39. 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
  • 40. Traits • Separate Concerns 40
  • 41. Traits •Separate Concerns • Precedence is based on declaration order 41
  • 42. Traits •Separate Concerns • Precedence is based on declaration order • All abstract – just like Java interface • None abstract – multiple inheritance 42
  • 43. Functions 43
  • 44. val reads = getSomeElectricReads // List[Read] reads.sort( (a,b) => a.date.compareTo(b.date) < 0 ) 44
  • 45. val reads = getSomeElectricReads // List[Read] reads.sort( (a,b) => a.date.compareTo(b.date) < 0 ) 45
  • 46. val reads = getSomeElectricReads // List[Read] reads.sort( (a,b) => a.date.compareTo(b.date) < 0 ) def sort(compFunc:(Read,Read) => Boolean) 46
  • 47. 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
  • 48. 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
  • 49. Methods are not Functions 49
  • 50. Methods are not Functions but can be passed as Functions 50
  • 52. class State(val code:String,val desc:String) val states = getAllStates // returns a List[String] with the codes states.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 matching states.filter( (state) => state.desc.startsWith(”V”) ) // Tons more 52
  • 53. Complete Access to JDK and Java libraries 53
  • 54. val s = new SingletonMetadataAwareAspectInstanceFactory() val foo = s.getOrderForAspectClass(classOf[FooBar]) 54
  • 55. import java.util.Observer import java.util.Observable class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date) } 55
  • 56. import java.util.Observer import java.util.Observable class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date) } 56
  • 57. import java.util.Observer import java.util.Observable class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date) } 57
  • 58. import java.util.Observer import java.util.Observable class AwesomeObserver extends Observer { def update(o:Observable, arg:Any) = if (o hasChanged) println(arg.asInstanceOf[MeterRead].date) } 58
  • 61. Proper F’ing Properties class ServicePoint(val id:String,var name:String) val sp = new ServicePoint(”foo”,”The Foo House”) println(sp.id) // get, but no set println(sp.name) sp.name = “Thy Foo Haüs” 61
  • 62. Proper F’ing Properties class 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
  • 63. ¡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
  • 64. ¡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
  • 65. 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 = 44 log.info(if read.usage < 10 “low read” else “high read”) 65
  • 66. 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 = 44 log.info(if read.usage < 10 “low read” else “high read”) 66
  • 67. 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 = 44 log.info(if read.usage < 10 “low read” else “high read”) 67
  • 68. 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 = 44 log.info(if read.usage < 10 “low read” else “high read”) 68
  • 69. 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 = 44 log.info(if read.usage < 10 “low read” else “high read”) 69
  • 70. “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
  • 71. “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
  • 72. “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 compiler creates a Tuple2[Boolean, String] 72
  • 73. “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
  • 74. “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 compiler val read2 = Read.apply(4,10,33) 74
  • 75. Crazy Awesome - Pattern Matching def fromEnglish(string:String) = string match { case “none” => 0 case “one” => 1 case _ => 2 } 75
  • 76. Crazy Awesome - Pattern Matching def 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
  • 77. Crazy Awesome - Pattern Matching sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 78. Crazy Awesome - Pattern Matching sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 79. Crazy Awesome - Pattern Matching sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 80. Crazy Awesome - Pattern Matching sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 81. Crazy Awesome - Pattern Matching sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 82. Crazy Awesome - Pattern Matching sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 83. Crazy Awesome - Implicits sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 84. Crazy Awesome - Implicits sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 85. Crazy Awesome - Implicits sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 86. Crazy Awesome - Implicits sealed abstract class Read case class AMIRead(date:Date,usage:Int,duration:Int) extends Read case class BillingRead(toDate:Date,usage:Int,numDays:Int,charges:Int) extends Read case 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
  • 87. Crazy Awesome - XML Literals val xml = <html> <head> <title>Scala Pronunciation Guide</title> </head> <body> <h1>How to Pronounce It</h1> </body> </html> println(xml) 87
  • 88. Crazy Awesome - XML Literals val lang = getLang val 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
  • 89. Crazy Awesome - XML Literals val lang = getLang val 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
  • 90. Crazy Awesome - XML Literals val 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
  • 94. Message Passing Immutable objects “actors” with “mailboxes” 94
  • 95. case class Accumulate(amount: Int) case class Reset case 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
  • 96. case class Accumulate(amount: Int) case class Reset case 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
  • 97. case class Accumulate(amount: Int) case class Reset case 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
  • 98. case class Accumulate(amount: Int) case class Reset case 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
  • 99. case class Accumulate(amount: Int) case class Reset case 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
  • 100. case class Accumulate(amount: Int) case class Reset case 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
  • 101. case class Accumulate(amount: Int) case class Reset case 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
  • 102. There’s a lot more to it 102
  • 103. Demo 103
  • 104. Demo Fill Gaps in Electric Meter Reads 104
  • 105. 6/1 6/2 6/4 6/5 6/8 5 kwh 7 kwh 3 kwh 5 kwh 8 kwh 105
  • 106. 6/1 6/2 6/4 6/5 6/8 5 kwh 7 kwh 3 kwh 5 kwh 8 kwh 6/3 6/6 6/7 ?? ?? ?? 106
  • 107. for all consecutive reads r1 and r2 if r2 - r1 > one day fill gaps for (r1,r2) 107
  • 108. 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
  • 109. 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
  • 110. 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
  • 111. 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
  • 112. 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
  • 114. It’s all happy flowers and meadows? 114
  • 115. It’s all happy flowers and meadows? not quite; a few stumbling blocks 115
  • 116. Generics, type-variance, etc. can get really confusing at times 116
  • 117. Library docs not as extensive as Java’s 117
  • 118. Still have to compile 118
  • 120. Symbol Soup sometimes ...but it gets easier 120
  • 121. Static typing sometimes paints you into a (very dark and confusing) corner 121
  • 122. sometimes you just need method_missing 122
  • 123. sometimes you just need monkey patching 123
  • 124. Where is Scala now? 124
  • 126. mailing lists, irc, a few blogs 126
  • 127. One good book, a few others 127
  • 128. Online docs improving, but scattered 128
  • 129. Spec is surprisingly readable 129
  • 130. Java is on the decline 130
  • 131. Java is on the decline and Ruby and Python aren’t the only options 131
  • 132. questions? 132