Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Scala

Introduction to Scala

Introduction to various features of the Scala programming language.

Aleksandar Prokopec

March 31, 2011
Tweet

More Decks by Aleksandar Prokopec

Other Decks in Programming

Transcript

  1. Introduction to Scala
    Aleksandar Prokopec
    EPFL

    View Slide

  2. View Slide

  3. Pragmatic
    Since
    2003
    runs on the JVM
    Seamless Java
    interoperability
    Statically typed
    Production
    ready
    Martin Odersky
    Hybrid

    View Slide

  4. Statically typed

    View Slide

  5. runs on the JVM

    View Slide

  6. Scala programs
    are fast.

    View Slide

  7. OOP + FP

    View Slide

  8. “I can honestly say if someone had shown me the Programming
    Scala book by Martin Odersky, Lex Spoon & Bill Venners back in
    2003 I'd probably have never created Groovy.“
    James Strachan, creator of Groovy

    View Slide

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

    View Slide

  10. Pragmatic

    View Slide

  11. Scala is lightweight.

    View Slide

  12. println(“Hello world!”)

    View Slide

  13. scala> println(“Hello world!”)
    Hello world!
    REPL
    evaluating expressions on the fly

    View Slide

  14. object MyApp extends App {
    println(“Hello world!”)
    }
    Compiled version

    View Slide

  15. object MyApp extends App {
    println(“Hello world!”)
    }
    Singleton objects
    no more static methods

    View Slide

  16. object MyApp {
    def main(args: Array[String]) {
    println(“Hello world!”)
    }
    }
    Declaring methods

    View Slide

  17. object MyApp {
    def main(args: Array[String]) {
    var user: String = args(0)
    println(“Hello, ”+user+“!”)
    }
    }
    Declaring variables

    View Slide

  18. object MyApp {
    def main(args: Array[String]) {
    val user: String = args(0)
    println(“Hello, ”+user+“!”)
    }
    }
    Declaring values
    prevents accidental changes

    View Slide

  19. object MyApp {
    def main(args: Array[String]) {
    val user = args(0)
    println(“Hello, ”+user+“!”)
    }
    }
    Local type inference
    less… “typing”

    View Slide

  20. class StringArrayFactory {
    def create: Array[String] = {
    val array: Array[String] =
    Array[String](“1”, “2”, “3”)
    array
    }
    }
    Local type inference
    less… “typing”

    View Slide

  21. class StringArrayFactory {
    def create = {
    val array = Array(“1”, “2”, “3”)
    array
    }
    }
    Local type inference
    less… “typing”

    View Slide

  22. // Scala
    class Person(
    var name: String,
    var age: Int
    )
    Declaring classes
    …concisely
    // Java
    public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }
    public String getName() {
    return name;
    }
    public int getAge() {
    return age;
    }
    public void setName(String name) {
    this.name = name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    }

    View Slide

  23. Scala is object-oriented.

    View Slide

  24. object Foo {
    val b = new ArrayBuffer[Any]
    }
    Object-oriented
    everything’s an object

    View Slide

  25. Object-oriented
    everything’s an object
    Any
    AnyRef
    AnyVal
    String
    Boolean
    Char
    Int

    View Slide

  26. object Foo {
    val b = new ArrayBuffer[Any]
    b += 1
    b += 1.toString
    b += Foo
    println(b)
    }
    Object-oriented
    everything’s an object

    View Slide

  27. 1 + 2
    1.+(2)
    Array(1, 2, 3) ++ Array(4, 5, 6)
    Array(1, 2, 3).++(Array(4, 5, 6))
    1 :: List(2, 3)
    List(2, 3).::(1)
    Operator overloading
    operators are methods

    View Slide

  28. trait Iterator[T] {
    def next(): T
    def hasNext: Boolean
    }
    Declaring traits
    traits are like interfaces

    View Slide

  29. trait Iterator[T] {
    def next(): T
    def hasNext: Boolean
    def printAll() =
    while (hasNext) println(next())
    }
    Declaring traits
    traits are rich

    View Slide

  30. trait Animal
    Multiple inheritance
    traits are composable

    View Slide

  31. trait Animal
    trait Mammal extends Animal {
    def think() = println(“hm...”)
    }
    Multiple inheritance
    traits are composable

    View Slide

  32. trait Animal
    trait Mammal extends Animal {
    def think() = println(“hm...”)
    }
    trait Bird extends Animal {
    def layEgg() = System.createEgg()
    }
    Multiple inheritance
    traits are composable

    View Slide

  33. View Slide

  34. trait Animal
    trait Mammal extends Animal {
    def think() = println(“hm...”)
    }
    trait Bird extends Animal {
    def layEgg() = System.createEgg()
    }
    class Platypus extends Bird with Mammal
    Mixin composition
    traits are composable

    View Slide

  35. trait Animal
    trait Reptile extends Animal {
    def layInTheSun: Unit = {}
    }
    class Dog(name: String) extends Mammal
    new Dog(“Nera”) with Reptile
    Dynamic mixin composition
    …or composition “on the fly”

    View Slide

  36. Cake pattern

    View Slide

  37. trait Logging {
    def log(msg: String)
    }
    trait AnsweringMachine {
    self: Logging with DAO with Protocol =>
    log(“Initializing.”)
    ...
    }
    Self-types
    to express requirements

    View Slide

  38. trait ConsoleLogging {
    def log(msg: String) = println(msg)
    }
    class LocalAnsweringMachine
    extends AnsweringMachine
    with ConsoleLogging
    with H2DAO
    with JabberProtocol
    Cake pattern
    layers above layers

    View Slide

  39. Scala is functional.

    View Slide

  40. (x: Int) => x + 1
    First class functions

    View Slide

  41. val doub: Int => Int = (x: Int) => x * 2
    doub(1)
     2
    First class functions
    functions are objects too

    View Slide

  42. val doub = (x: Int) => x * 2
    List(1, 2, 3).map(doub)
     List(2, 4, 6)
    First class functions
    as higher order parameters

    View Slide

  43. List[Int](1, 2, 3).map((x: Int) => x * 2)
    // more type inference
    List(1, 2, 3).map(x => x * 2)
    // or even shorter
    List(1, 2, 3).map(_ * 2)
    Functions with sugar
    make code sweeter

    View Slide

  44. var step = 1
    val inc = x => x + step
    inc(5)
     6
    step = 2
    inc(5)
     7
    Closures
    functions that “capture” their environment

    View Slide

  45. // Java
    button.addMouseListener(new MouseAdapter() {
    public void mouseEntered(MouseEvent e) {
    System.out.println(e);
    }
    }
    // Scala
    listenTo(button)
    reactions += { case e => println(e) }
    First class functions
    because you write them in Java all the time

    View Slide

  46. Pattern matching

    View Slide

  47. Pattern matching
    …is concise
    // Scala
    reactions += {
    case m: MouseEntered =>
    println(“I see it!”)
    case m: MouseExited =>
    println(“Lost it.”)
    case m: MouseClicked =>
    println(“Poked!”)
    }
    // Java
    button.addMouseListener(new MouseAdapter() {
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {
    System.out.println(“I see it!”);
    }
    public void mouseExited(MouseEvent e) {
    System.out.println(“Lost it.”);
    }
    public void mouseClicked(MouseEvent e) {
    System.out.println(“Poked!”);
    }
    }
    // ...alternative - isinstanceof

    View Slide

  48. trait Tree
    case class Node(l: Tree, r: Tree)
    extends Tree
    case object Leaf
    extends Tree
    Pattern matching
    …is precise

    View Slide

  49. def b(t: Tree): Int = t match {
    case Node(Leaf, Node(_, _)) |
    Node(Node(_, _), Leaf) => -1
    case Node(l, r) =>
    val (ld, rd) = (b(l), b(r))
    if (ld == rd) ld + 1 else -1
    case Leaf => 0
    case _ => error(“Unknown tree!”)
    }
    Pattern matching
    …is precise

    View Slide

  50. sealed trait Tree
    ...
    def b(t: Tree): Int = t match {
    case Node(Leaf, Node(_, _)) |
    Node(Node(_, _), Leaf) => -1
    case Node(l, r) =>
    val (ld, rd) = (b(l), b(r))
    if (ld == rd) ld + 1 else -1
    case Leaf => 0
    }
    Pattern matching
    …is exhaustive

    View Slide

  51. def matchingMeSoftly(a: Any): Any =
    a match {
    case 11 => “eleven”
    case s: String => “’%s’”.format(s)
    case {t} => t
    case Array(1, 2, 3) => “1, 2, 3”
    case head :: tail => tail
    case _ => null
    }
    Pattern matching
    …is extensible

    View Slide

  52. Lazyness

    View Slide

  53. lazy values
    don’t compute if there’s no demand
    class User(id: Int) {
    lazy val followernum =
    from(followers)(f =>
    where(id === f.fid)
    compute(countDistinct(f.fid))
    )
    }

    View Slide

  54. Call by name
    evaluate only when you have to
    def withErrorOut(body: =>Unit) = {
    val old = Console.out
    Console.setOut(Console.err)
    try body
    finally Console.setOut(old)
    }
    ...
    withErrorOut {
    if (n < 0) println(“n too small”)
    }

    View Slide

  55. Streams
    lazy lists
    e = ∑ 1/n!
    = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …

    View Slide

  56. Streams
    lazy lists
    e = ∑ 1/n!
    = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …
    0! ?

    View Slide

  57. Streams
    lazy lists
    e = ∑ 1/n!
    = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …
    0! 1! 2! 3! ?
    0! ?

    View Slide

  58. Streams
    lazy lists
    e = ∑ 1/n!
    = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …
    0! 1! 2! 3! ?
    0! ?
    0! 1/1! 1/2! 1/3! ?

    View Slide

  59. Streams
    lazy lists
    def fact(n: Int, p: Int): Stream[Int] =
    p #:: fact(n + 1, p * (n + 1))
    val factorials = fact(0, 1)
    val e = factorials.map(1./_).take(10).sum

    View Slide

  60. Scala is expressive.

    View Slide

  61. for comprehensions
    traverse anything
    for (x <- List(1, 2, 3)) println(x)
    List(1, 2, 3).foreach(x => println(x))
    for (x <- 0 until 10) println(x)
    (0 until 10).foreach(x => println(x))
    Range(0, 10, 1).foreach(x => println(x))

    View Slide

  62. for comprehensions
    map anything
    for (x <- List(1, 2, 3)) yield x * 2
    List(1, 2, 3).map(x => x * 2)
    for (x <- List(1, 2); y <- List(1, 2))
    yield x * y
    List(1, 2).flatMap(x =>
    List(1, 2).map(y => x * y)
    )
     List(1, 2, 2, 4)

    View Slide

  63. for comprehensions
    like SQL queries
    for {
    p <- people
    if p.age > 25
    s <- schools
    if p.degree == s.degree
    } yield (p, s)
    // pairs of people older than 25 and
    // schools they possibly attended

    View Slide

  64. Collections
    easy to create
    val phonebook = Map(
    “Jean” -> “123456”,
    “Damien” -> “666666”)
    val meetings = ArrayBuffer(
    “Dante”, “Damien”, “Sophie”)
    println(phonebook(meetings(1)))

    View Slide

  65. Collections
    high-level combinators
    // Java
    boolean isOk = true
    for (int i = 0; i < name.length(); i++) {
    if (isLetterOrDigit(name.charAt(i)) {
    isOk = false;
    break;
    }
    }

    View Slide

  66. Collections
    high-level combinators
    // Scala
    name.forall(_.isLetterOrDigit)

    View Slide

  67. Collections
    high-level combinators
    // count the total number of different
    // surnames shared by at least 2 adults
    people

    View Slide

  68. Collections
    high-level combinators
    // count the total number of different
    // surnames shared by at least 2 adults
    people.filter(_.age >= 18)

    View Slide

  69. Collections
    high-level combinators
    // count the total number of different
    // surnames shared by at least 2 adults
    people.filter(_.age >= 18)
    .groupBy(_.surname): Map[String, List[Person]]

    View Slide

  70. Collections
    high-level combinators
    // count the total number of different
    // surnames shared by at least 2 adults
    people.filter(_.age >= 18)
    .groupBy(_.surname): Map[String, List[Person]]
    .count { case (s, l) => l.size >= 2 }

    View Slide

  71. Lists
    an immutable sequence
    val countdown = List(3, 2, 1)
    3 2 1
    countdown

    View Slide

  72. Lists
    an immutable sequence
    val countdown = List(3, 2, 1)
    val longer = 4 :: countdown
    3 2 1
    4
    countdown
    longer

    View Slide

  73. Lists
    an immutable sequence
    val countdown = List(3, 2, 1)
    val longer = 4 :: countdown
    val fast = 10 :: countdown
    3 2 1
    4
    10
    countdown
    longer
    fast

    View Slide

  74. Lists
    an immutable sequence
    val countdown = List(3, 2, 1)
    val longer = 4 :: countdown
    val fast = 10 :: countdown
    val withzero = countdown ::: List(0)
    3 2 1
    4
    10
    3 2 1 0
    countdown
    longer
    fast
    withzero

    View Slide

  75. Buffers
    mutable sequences
    val b = ArrayBuffer(1, 2, 3)
    b += 4
    b += 5
    b += 6
     ArrayBuffer(1, 2, 3, 4, 5, 6)

    View Slide

  76. Maps
    mutable or immutable, sorted or unsorted
    import collection._
    val m = mutable.Map(“Heidfeld” -> 1,
    “Schumacher” -> 2)
    m += “Hakkinen” -> 3
    val im = immutable.Map(“Schumacher” -> 1)

    View Slide

  77. Hash tries
    persistence through efficient structural sharing
    val im0: Map[Int, Int] = ...
    im0

    View Slide

  78. Hash tries
    persistence through efficient structural sharing
    val im0: Map[Int, Int] = ...
    val im1 = im0 + (1 -> 1)
    im0 im1

    View Slide

  79. Hash tries
    persistence through efficient structural sharing
    val im0: Map[Int, Int] = ...
    val im1 = im0 + (1 -> 1)
    val im2 = im1 + (2 -> 2)
    im0 im1 im2

    View Slide

  80. Hash tries
    persistence through efficient structural sharing
    val im0: Map[Int, Int] = ...
    val im1 = im0 + (1 -> 1)
    val im2 = im1 + (2 -> 2)
    val im3 = im2 + (3 -> 6)
    im0 im1 im2 im3

    View Slide

  81. Hash tries
    persistence through efficient structural sharing
    im0 im1 im2 im3
    2x-3x slower lookup
    2x faster iteration

    View Slide

  82. Parallel collections
    parallelize bulk operations on collections
    def cntEqlen(m: Map[String, String]) = {
    m.par.count {
    case (n, s) => n.length == s.length
    }
    }
    // be careful with side-effects

    View Slide

  83. Scala is extensible.

    View Slide

  84. One ring to rule them all.

    View Slide

  85. actors
    road to safer concurrency
    val a = actor {
    react {
    case i: Int => println(i)
    }
    }
    ...
    a ! 5

    View Slide

  86. Custom control flow
    it’s all about control
    def myWhile(c: =>Boolean)(b: =>Unit) {
    if (c) {
    b
    myWhile(c)(b)
    }
    }

    View Slide

  87. Custom control flow
    it’s all about control
    @tailrec
    def myWhile(c: =>Boolean)(b: =>Unit) {
    if (c) {
    b
    myWhile(c)(b)
    }
    }

    View Slide

  88. Custom control flow
    it’s all about control
    @tailrec
    def myWhile(c: =>Boolean)(b: =>Unit) {
    if (c) {
    b
    myWhile(c)(b)
    }
    }
    var i = 0
    myWhile (i < 5) {
    i += 1
    }

    View Slide

  89. ARM
    automatic resource management
    withFile (“~/.bashrc”) { f =>
    for (l <- f.lines) {
    if (“#”.r.findFirstIn(l) != None)
    println(l)
    }
    }

    View Slide

  90. ScalaTest
    behavioral testing framework
    “A list” should {
    “be a double reverse of itself” in {
    val ls = List(1, 2, 3, 4, 5, 6)
    ls.reverse.reverse should equal (ls)
    }
    }

    View Slide

  91. BaySick
    Basic DSL in Scala
    10 PRINT “Baysick Lunar Lander v0.9”
    20 LET ('dist := 100)
    30 LET ('v := 1)
    40 LET ('fuel := 1000)
    50 LET ('mass := 1000)
    ...

    View Slide

  92. implicit conversions
    augmenting types with new operations
    ‘a’.toUpperCase

    View Slide

  93. implicit conversions
    augmenting types with new operations
    implicit def charOps(c: Char) = new {
    def toUpperCase =
    if (c >= ‘a’ && c <= ‘z’)
    (c – 32).toChar
    else c
    }
    ...
    ‘a’.toUpperCase

    View Slide

  94. Pimp my library

    View Slide

  95. implicit conversions
    pimping your libraries since 2006
    import scalaj.collection._
    val list = new java.util.ArrayList[Int]
    list.add(1)
    list.add(2)
    list.add(3)
    ...
    for (x <- list) yield x * 2

    View Slide

  96. implicit conversions
    pimping your libraries since 2006
    import scalaj.collection._
    val list = new java.util.ArrayList[Int]
    list.add(1)
    list.add(2)
    list.add(3)
    ...
    for (x <- list) yield x * 2
    // list.map(x => x * 2)

    View Slide

  97. implicit conversions
    pimping your libraries since 2006
    import scalaj.collection._
    val list = new java.util.ArrayList[Int]
    list.add(1)
    list.add(2)
    list.add(3)
    ...
    for (x <- list) yield x * 2
    // jlist2slist(list).map(x => x * 2)

    View Slide

  98. implicit arguments
    restricting operations on types
    val is = SortedSet(1, 2, 3)
    case class Man(id: Int)
    ...
    implicit object MenOrd extends Ordering[Man] {
    def compare(x: Man, y: Man) = x.id – y.id
    }
    val ms = SortedSet(Person(1), Person(2))

    View Slide

  99. STM
    software transactional memory
    val account1 = cell[Int]
    val account2 = cell[Int]
    atomic { implicit txn =>
    if (account2() >= 50) {
    account1 += 50
    account2 -= 50
    }
    }

    View Slide

  100. Scala has support.

    View Slide

  101. Building
    Ant
    SBT
    Maven

    View Slide

  102. SBT
    simple build tool
    > compile
    ...
    > ~compile
    ...
    > test
    ...
    > package

    View Slide

  103. SBT
    project definition written in Scala
    val scalatest =
    “org.scala-tools.testing” %
    “scalatest” % “0.9.5”
    ...
    > reload
    [INFO] Building project ...
    [INFO] using sbt.Default ...
    > update

    View Slide

  104. Tools: IDEs
    Eclipse
    Netbeans
    IntelliJ IDEA
    Emacs
    ENSIME
    JEdit

    View Slide

  105. Web frameworks

    View Slide

  106. Used by...

    View Slide

  107. Thank you!

    View Slide