scala-intro-slides



scala-intro-slides

0 0


scala-intro-slides


On Github kipsigman / scala-intro-slides

Intro to Scala

Scala SB, 5/22/2014

Kip Sigman (Typesafe), Joe Zulli (Fmr: CTO @ Savings.com)

When?

  • 2003: First experimental release.
  • 2005: Scala 2.0 written in Scala.
  • 2011: Typesafe founded.
  • April 2014: Scala 2.11.0 released.

What?

  • Hybrid language: Objected Oriented and Functional.
  • Runs on the JVM (like Clojure, Groovy, JRuby, etc).
  • Emphasizes declarative vs. imperative programming.

Why?

Who?

http://typesafe.com/company/casestudies

Language Basics

Declaring Values with Type Inference

val number: Int = 5
val name: String = "Joe"

Could be re-written as

val number = 5
val name = "Joe"

EVERYTHING is an Object

5.toString // res0: String = 5

And I mean everything

val add: (Int, Int) => Int = _ + _

add.toString // res1: String = <function2>

And... Everything is an Expression

val resultString = if(wasSuccessful) "Success" else "Failed"


val otherResultString = try {
  doSomething
  "Success"
} catch {

  e: Exception => "Failed"
}


val list: Seq[String] = for (i <- 1 to 10) yield s"Hello $i"

Plays Nicely with the Host Organism

import java.util.Random
def randomInt: Int = new Random().nextInt()

Symbolic Method Names

case class Duration(seconds: Int) {

  override def toString: String = seconds + " seconds left"

  def +(other: Duration) = Duration(seconds + other.seconds)

  def -(other: Duration) = Duration(seconds - other.seconds)
}

In use

 val d1 = Duration(10)
 val d2 = Duration(7)

 val result = d1 - d2 // same as d1.-(d2)
 //result: Duration = 3 seconds left
}

OO features

Case Classes

case class User(name: String, email: String, age: Int)

The Java Equivalent

final class User {

  private final String name;
  private final String email;
  private final int age;

  public User(final String name, final String email, final int age) {

    this.name = name;
    this.email = email;
    this.age = age
  }

  public String getName() { return this.name; }
  public String getEmail() { return this.email; }
  public int getAge() { return this.age; }

  public String toString() {

    return "User(name=" + name + ",email=" + email + ",age=" + age + ")";
  }

  public boolean equals(User other) {

    return this.name.equals(other.name) &&
          this.email.equals(other.email) &&
          this.age == other.age;
  }

  public int hashCode() {

    // I don't remember how to do hash codes
  }

}

Singletons

object UserService {

  def findUserByName: Option[User] = ...
}

Functional Programming Features

Higher Order Functions

case class User(name: String, age: Int)

val users: List[User] = User("Joe", 22) :: User("Bob", 43) ::
                        User("Kip", 56) :: Nil

// can also be written val toName: User => String = _.name
val toName: User => String = user => user.name

val userNames: List[String] = users.map(toName)

// more concise syntax
val userNames = users.map.(user => user.name)

Options

def getUserFromDb(id: Int): User = // DB stuff

val userMap = Map("Joe" -> 1, "Bob" -> 2, "Kip" -> 3)

val bobsId: Option[Int] = userMap.get("Bob")
// Some(Int) OR None

val bob: Option[User] = bobsId.map(getUserFromDb)

Pattern matching

val bob: Option[User] = ....

def printAge(user: Option[User]) = user match {
  case None => println("No user here")
  case Some(u) => println(s"The age is: ${u.age}")
}

Pattern Matching Continued

Find Bob and return his age

case class User(name: String, age: Int)

val users: List[User] = User("Joe", 22) :: User("Bob", 43) ::
            User("Kip", 56) :: Nil

def getAge(name: String,
           users: List[User]): Option[Int] = users match {

  case Nil => None
  case User(n, age) :: tail if n == name => Some(age)
  case head :: tail => getAge(name, tail)
}
getAge("Bob", users)
//res0: Option[Int] = Some(43)

Collection Awesomeness

// get all users who are 25 years old or older
val canRentCars = users.filter(u => u.age >= 25)
// canRentCars: List[User] = List(User(Bob,43), User(Kip,56))

More Collection Awesomeness

// divide the list into two sub-lists as determined
// by whether the users are kids or adults
val (kids, adults) = users.partition(u => u.age < 18)
// kids: List[User] = List()
// adults: List[User] = List(User(Joe,22), User(Bob,43), User(Kip,56))

MOAR Collection Awesomeness

// partition, but what if the function is a
// big expensive operation???
val horriblySlowFunc = user => ...
val (l1, l2) = users.par.partition(horriblySlowFunc)

Find Bob and Return his Age REDUX

What we had before

case class User(name: String, age: Int)

val users: List[User] = User("Joe", 22) :: User("Bob", 43) ::
            User("Kip", 56) :: Nil

def getAge(name: String,
           users: List[User]): Option[Int] = users match {

  case Nil => None
  case User(n, age) :: tail if n == name => Some(age)
  case head :: tail => getAge(name, tail)
}
getAge("Bob", users)
//res0: Option[Int] = Some(43)

Find Bob and Return his Age REDUX

But with Scala collections, you can easiliy do it in one line

case class User(name: String, age: Int)

val users: List[User] = User("Joe", 22) :: User("Bob", 43) ::
            User("Kip", 56) :: Nil

def getAge(name: String,
           users: List[User]): Option[Int] = {

  users.find(u => u.name == name).map(u => u.age)
}
getAge("Bob", users)
//res0: Option[Int] = Some(43)

Criticism

  • Compiler is a dog.
  • Binary incompatibility between versions.
  • Hard to read, hard to learn.
  • Tools suck.
  • Java 8 makes Scala unnecessary.

Next?

Cool "advanced" features

  • Implicits & DSLs
  • Futures & Promises

Frameworks

Resources