Derek Chen-BeckerDerek Chen-BeckerSenior Network EngineerSenior Network Engineer
CPI CorporationCPI Corporation
Starting with ScalaStarting with Scala
Frontier Developers' MeetupFrontier Developers' MeetupDecember 9December 9thth, 2010, 2010Boulder, COBoulder, CO
Scala's Pedigree
Created by Martin Odersky (EPFL), of GJ, and later Javac v5 fame
Scala's History
Jan 04 Jan 05 Jan 06 Jan 07 Jan 08 Jan 09 Jan 10
1.1.
1.0
1.2.
0.0
1.3.
0.2
1.4.
0.0
2.1.
0 2.2.
02.
3.0
2.4.
02.
5.0
2.6.
0 2.7.
0
2.8.
0
2.8.
1
Scala History
2.7.1 - 2.7.7
More Info on Scala
Home page: http://www.scala-lang.org/Excellent community
[email protected]://chat.freenode.net/scalahttp://scala.sygneca.com/ (Wiki)
Scala in Print
Scala in the Real World
Scala and the JVM
Compiles to 100% Java BytecodeGenerally works flawlessly with JavaLeverages JIT: performance ±5% of Java
Full access to existing Java ecosystemCLR (.Net) port in progress
About This Talk
Scala 2.8.0+Significant changes to libraryI'm still coming up to speed on them
This is not a lecture
Act INo Time Like the Present
The Scala REPL
Read, Evaluate, Print, LoopYou need a JVM (1.6+ preferred) with “java” in your path or JAVA_HOME setDownload the latest binaries from http://www.scala-lang.org/downloadsUnpack wherever, go to bin subdirectoryType “scala<enter>”
Act IISo, What is Scala?
Three Very Common Keywords
val – defines an immutable value or referencevar – defines a mutable valuedef – defines a function/method
Scala is Concerned with Mutability
Immutable data structures reduce (but not eliminate) concurrency issuesCombined with actors make a powerful approach to parallel tasksStrong library and language support
Scala is Strongly Typed...
val foo : Int = 12
var bar : String = "twelve"
def baz (in : Int) : Double = in.toDouble
...But Can Usually Figure Types Out
val foo = 12
var bar = "twelve"
def baz (in : Int) = in.toDouble
Scala is Generic
val primes : List[Int] = List(2,3,5,7,11)
scala> primes.grouped(2).toListres16: List[List[Int]] = List(List(2, 3), List(5, 7), List(11))
Scala is ObjectOriented
class Foo { def bar () = { "bat" }}
val f = new Foo
I Mean Really ObjectOriented
scala> (12.5).min(47) res17: Double = 12.5
scala> 3825.toHexStringres18: String = ef1
scala> '5'.isWhitespaceres19: Boolean = false
Primitives are treated as 1st class objects
Scala is Functional
val greet = (name : String) => "Hello, %s!".format(name)
greet(“Fred”)res27: String = Hello, Fred!
val greet = "Hello, %s!".format(_ : String)
Scala is Functional Everywhere
def doubleMe (f : () => Any) { println(f()); println(f());}
scala> doubleMe(System.nanoTime) 15885045173037341588504517365296
Scala is Closurific
def counter (name : String) = { var i = 0; { () => i += 1 name + ":" + i } }
Scala is Concise...
public class Person { private String name; private int age;
public Person(String name, int age) { super(); this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int hashCode() {...} public String toString() {...} public boolean equals() {...} }
VScase class Person(name : String, var age : Int)
...But Maintains Uniform Access
case class Person(val name : String, private var curAge : Int) { def age = curAge def age_= (a : Int) { curAge = a }}
Scala is DSLFriendly (be reasonable)
class Vector[T](data : Array[T]){ def + (that : Vector[T]) = {} def - (that : Vector[T]) = {} ... def ⊗ (that : Vector[T]) = {}}
val product = A B⊗val product = A. (B)⊗
Scala is Optional
val exists: Option[Int]= Some(42)val notHere: Option[Int] = None
scala> exists.map(_ * 2).getOrElse(12) res0: Int = 84
scala> notHere.map(_ * 2).getOrElse(12)res1: Int = 12
Scala Likes Tuples (Heterogeneous)
scala> val state = (12, "Empty", RED)state: (Int, java.lang.String, java.awt.Color) = (12,Empty,java.awt.Color[r=255,g=0,b=0])
scala> val (count, description, color) = statecount: Int = 12description: java.lang.String = Emptycolor: java.awt.Color = java.awt.Color[r=255,g=0,b=0]
Scala is XMLFriendly
def personToXml(p : Person) = <person name={p.name} age={p.age.toString} />
Scala is HighLevel...
val people = List(Person("Fred", 30), Person("Ted", 25), Person("Ed", 41))
people.foreach (println)
Letting You Get to the Real Work
// One line of magic...implicit val orderPeople = Ordering.by((_:Person).age)
// ...allows powerful constructsval (oldest,youngest) = (people.max,people.min)
Act IIIScala OO Fundamentals
Packages
package net.foo { ...}
package net.foo
Imports
import java.io.Fileimport java.net._import java.awt.{Image, Color => JCol, Dialog => _}
Packages Nest...
package net.foo==
package net { package foo { ... }}
Sometimes in Unexpected Ways (< 2.8)
package net.foo { import java.net.URL}
The Scala OO Quadfecta
class object
trait
case class/object
Traits Are Good
Somewhat analogous to interfaces...
trait Comparable[T] { def < (that : T) : Boolean def <= (that : T) : Boolean def > (that : T) : Boolean def >= (that : T) : Boolean}
Traits are Really Awesome
...But they can carry implementation
trait Comparable[T <: Comparable[T]] { self : T => def < (that : T) : Boolean def <= (that : T) = this < that || this == a def > (that : T) = that < this def >= (that : T) = that <= this}
Traits can be Composed
trait Atrait Btrait C
class Base extends A with B with C
Class Linearization : Base Trait
trait Pet { def greeting : String def eat() : Unit}
Class Linearization : Extension Traits
trait Dog extends Pet { def greeting = "Woof" def eat() {...}}
trait Mute extends Pet { override val greeting = ""}
Class Linearization : Composition
class Dingo extends Dog with Mute
scala> (new Dingo).greetingres0: java.lang.String =
Scala Objects
“An object definition defines a single object of a new class” (Scala Reference, §5.4
object Friendly { var publicInt = 0 def hi = println("Hi!")}
Objects hold Static Methods
object MyApp { def main (args : Array[String]) { ... }}
Objects are Scoped VM Singletons
class Outer { object Inner { var foo = "foo" }}
Objects as Factories
object Person { def apply(name : String, age : Int) : Person = new Person(name,age)}
val fred = Person("Fred", 20)
Objects as Factories, Continued
object Person { ... def apply(name : String) : Person = new Person(name, 1)}
val babyFred = Person("Fred")
Named and Default Arguments
object Person { def apply(name : String, age : Int = 1) : Person = new Person(name,age)}
val fredBaby = Person(name = "Fred")
Case Classes (and Objects)
case class Car (name : String, gears : Int)
scala> val myCar = Car("Corolla", 4)myCar: Car = Car(Corolla,4)
scala> myCar.name res0: String = Corolla
Case Class Automation
Factory method (apply)toStringhashCodeequals (and therefore ==)Constructor params become vals, can be turned into vars
Case Class Bonii : Copy
scala> val myCar = Car("Corolla", 4)myCar: Car = Car(Corolla,4)
scala> val myOtherCar = myCar.copy(name = "Forester")myOtherCar: Car = Car(Forester,4)
Case Class Bonii : Extraction
scala> val myCar = Car("Corolla", 4)myCar: Car = Car(Corolla,4)
// “_” here means “don't bother”scala> val Car(_,gears) = myCargears: Int = 4
Act IVFunctional is Your Friend
Start With Some Basic Functions
foreachmapflatMapfilterexiststakeWhiledropWhile
Composing Functions == Power
people.flatMap(first => people.filter(_ != first). map(List(first,_)))
For Comprehensions
for (first <- people; second <- people if first != second) yield List(first,second)
Currying
def scaler (factor : Int) (value : Int) = factor * value
val times2 = scaler(2) _times2(12) // == 24
Provide N argument lists, but only use 1 to N-1 of them to define a new function
“By Name” Arguments
def myWhile (condition : => Boolean) (f : => Unit) { if (condition) { f; myWhile(condition)(f) }}
“By Name” Use Case : Logging
if (logger.isDebugEnabled) { logger.debug("Foo: " + foo)}
“By Name” Use Case : Logging
if (logger.isDebugEnabled) { logger.debug("Foo: " + foo)}
THIS SUCKS
“By Name” to the Rescue
def debug (msg : => String) { if (this.debugEnabled) { println(msg) }}
https://github.com/weiglewilczek/slf4s
Pattern Matching : Switch on Steroids
“case _” here is the default casedef literalMatch (in: Any) { in match { case 1 => doBar("One") case "test" => doBar("test") case 'x' => doBar("x") case 2.2f => doBar("float") case _ => doBar("lemon curry?") }}
Pattern Matching : Alternate Matches
Using “|” allows multi-match cases
def literalMatch (in: Any) { in match { case 1 | 2 | 3 => doBar("One to three") case "this" | "that" => doBar("the other") case _ => doBar("lemon curry?") }}
Pattern Matching : XML
def xmlMatch (in : Any) = in match { case <people>{bar @ _*}</people> => bar.foreach(println) case _ => // NOOP}
Pattern Matching : Case Classes
def caseMatch (a : Any) = a match { case Person(name, age) => println("%s is %d”. format(name,age))}
Pattern Matching : Type Matches
def typeMatch (in: Any) { in match { case i : Int => doBar("Int : " + i) case s : String => doBar(s) case _ => // NOOP }}
Pattern Matching : Generics
Erasure is not your friend
def typeMatch (in: Any) { in match { case ls : List[String] => doBar("danger!") case li : List[Int] => doBar("never happens") case _ => // NOOP }}
Pattern Matching : Guards
def guardMatch (in: Any) { in match { case i : Int if i > 12 && i < 47 => doBar("Int : " + i) case _ => // NOOP }}
Pattern Matching : Generics Workaround
Like duck tape : ugly, but effective
def typeMatch (in: Any) { in match { case ls : List[_] if ls.forall(_.isInstanceOf[String]) => doBar("Strings!") case li : List[_] => doBar("Some kind of List") case _ => // NOOP }}
More More Info on Scala
Home page: http://www.scala-lang.org/Excellent community
[email protected]://chat.freenode.net/scalahttp://scala.sygneca.com/ (Wiki)
Top Related