A gentle introduction toScala & its ecosystem – IDE support – Scala-IDE (Eclipse plugin)



A gentle introduction toScala & its ecosystem – IDE support – Scala-IDE (Eclipse plugin)

0 0


funlx-meetup

My talk “Gentle Introduction to Scala And Its Ecosystem” at the Fun(Lx) meetup http://www.meetup.com/Fun-Lx/events/165949652/

On Github stanch / funlx-meetup

A gentle introduction toScala & its ecosystem

Nickhttp://github.com/stanch

Who…

…makes Scala?

…uses Scala?

Part 1

Main features

Scala at a glance

  • General-purpose
  • Object-Oriented + Functional
  • Clarity + Scalability
  • Compiles to JVM & JS

Types

Static and Strong

val x: Int = 4
val y: List[Int] = List(1, 2)

Happily inferred

val x = 4
val y = List(1, 2)

Values

Values can’t change

val x = 4

Variables can

var x = 4
x += 3

Lazy values don’t compute until accessed

lazy val z = launchMissiles() // nothing happens
...
z // missiles launched!

Expressions

Everything is an expression

val p = {
  val ab = a + b
  val cd = c + d
  ab + cd // last line is returned
}

val x = if (2 > 0) "Plausible" else "No way"

def f(a: Int) = a + 1

def biggerFunction(a: Int, b: Int) = {
  val z = a + b * 3 - 4 * a * b
  z + 9
}

Classes & objects

Classes

class Person(firstName: String, lastName: String) {
  // properties
  val name = firstName + " " + lastName

  // methods
  def greetMe(greeting: String) = println(s"$greeting, $name")

  // everything inside body runs on construction
  println("I have been born")
}

val person = new Person("Nick", "Stanchenko")
assert(person.name == "Nick Stanchenko")

Singletons

object World {
  val a = 4
  val b = 9
}
assert(World.a + World.b == 13)

Traits

Mixins

trait Barking {
  def bark() = println("bark")
}

trait Meowing {
  def meow() = println("meow")
}

class CatDog extends Barking with Meowing

Partial implementations

trait Greetable {
  val name: String // needs implementation

  val greeting = "Hi"
  def greet() = println(s"$greeting, $name")
}

class Person(firstName: String, lastName: String) extends Greeting {
  val name = s"$firstName $lastName"
}

Functions

Methods

// can have default values and named arguments
def m(x: Int, y: String = "default") = x.toString + y
m(3)
m(x = 9, y = "foo")

// can have type parameters
def n[A, B](x: A, y: B) = ???

Functions (function values)

// full declaration
val f: Function1[Int, Int] = (x: Int) ⇒ x + 1
val f: Int ⇒ Int = (x: Int) ⇒ x + 1

// with type annotation
val f: Int ⇒ Int = x ⇒ x + 1
val f: Int ⇒ Int = _ + 1

// with argument annotation
val f = (x: Int) ⇒ x + 1
val f = { x: Int ⇒
  ...
}

Flexible syntax

All methods are unicode operators (don’t overdo it)

3.+(3) // same as 3 + 3
class Bird {
  def ♫(song: String) = println(song * 3)
  def sing(song: String) = ♫(song)
}
val bird = new Bird
bird ♫ "twitt" // same as bird.♫("twitt")
bird sing "twitt" // same as bird.sing("twitt")

Single parameters can go in braces

bird ♫ {
  ...
}

Multiple parameter groups

def f(x: Int)(y: Int) = x * y
f(3) {
  val z = 8 + 9
  z - 1
}

Pattern matching

Simple patterns

(x, y) match {
  case (3, _) ⇒ 9
  case (_, p) if p > 8 ⇒ 10
  case (p, q) ⇒ p + q
}

val List(x, y, _*) = List(1, 2, 3, 4, 5)

Case classes

case class Person(name: String, age: Int, partner: Option[Person])

p match {
  case Person(_, a, _) if a > 18 ⇒ true
  case Person(_, _, Some(Person(n, a, _))) if n.length > a ⇒ false
  case Person("Bobby", _, None) ⇒ true
  case _ ⇒ false
}

val Person(name, age, _) = p
assert(age == 19)

Implicits

Parameters the compiler knows

def foo(bar: String)(implicit config: Config) = ...

// explicit
foo("bar")(new Config("baz"))

// implicit
implicit val c = new Config("baz")
...
foo("bar") // c: Config found and inserted

“Pimp my library”

implicit class PimpedInt(x: Int) {
  def times[A](f: Int ⇒ A)
}

5 times { i ⇒
  println(i)
}

Macros (info)

User writes

myButton.on("click", alert("Hi"))

At compile-time, this expands into

myButton.setOnClickListener(new View.OnClickListener {
  def onClick(v: View) = alert("Hi!")
})

You can write code that generates code!

Part 2

Libraries and applications

Overview

  • Cool functional collections
  • Fantastic concurrency support
  • Web, GUI

Collections

Anonymous function paradise

val x = List(1, 2, 3).map(i ⇒ i + 1).filter(i ⇒ i > 2)

// or
val x = List(1, 2, 3).map(_ + 1).filter(_ > 2)

// or
val x = List(1, 2, 3) map { i ⇒
  val z = doSomethingWith(i)
  s"$z is a number, but I’m a string"
}

Methods for everything

def digitSum(x: Int) = x % 10 + (x / 10 % 10)

val (cool, notCool) = (1 to 100)
  .sortBy(digitSum)
  .take(50)
  .drop(25)
  .partition(_ % 4 == 0)

val reallyCool = cool.find(_ > 500).getOrElse(123)

Futures (info)

Predicting the future

// an int will be here... some time...
val x: Future[Int] = Future {
  Thread.sleep(3)
  4
}

// print it when it comes
x onSuccess println

// or report if an exception comes instead
x onFailure println

Futures are like collections!

// another Future
val y = x.map(_ + 1)

// a future that depends on x and y
val z = (x zip y) map { case (resultX, resultY) ⇒
  resultX + resultY
}

// failure from x or y is propagated!
z onFailure println

Async (info)

Juggle futures with ease

// our futures
val x: Future[Int] = ...
val y: Future[Int] = ...

// no blocking here!
val z: Future[Int] = async {
  await(x) + await(y)
}

Entire async workflows

async {
  val data = await(getDataFromDatabase(38))
  val processed = await(processData(data))
  await(prettify(processed))
}

Akka (info)

Actors

class A extends Actor {
  def receive = {
    case Message(x) ⇒ ...
    case OtherMessage(y, z) ⇒ ...
  }
}

Ping-ping

case class Ping(x: Int)

class A extends Actor {
  context.actorSelection("../b") ! Ping(22)
  def receive = {
    case Ping(x) ⇒ sender ! Ping(x + 1)
  }
}

class B extends Actor {
  def receive = {
    case Ping(x) ⇒ sender ! Ping(x + 2)
  }
}

Spray (info)

  • Uses Akka
  • Actors handle HTTP requests
  • Connects Actor system to the web

Routing DSL

startServer(interface = "localhost", port = 8080) {
  path("hello") {
    get {
      complete {
        "<h1>Say hello to spray</h1>"
      }
    }
  } ~
  path("test" / IntNumber) { number ⇒
    post {
      complete("OK")
    }
  }
}

Macroid (info)

Android DSL

var greeting = slot[TextView]
l[LinearLayout](
  w[Button] ~>
    text("Greet me!") ~>
    On.click {
      greeting ~> text("Hello there") ~> show
    },
  w[TextView] ~> hide ~> wire(greeting)
)

Composition

def caption(cap: String): Tweak[TextView] = text(cap) + TextSize.large
w[TextView] ~> caption("I’m a caption!")

Futures?

val futureCaption: Future[Tweak[TextView]] = myFuture.map(text ⇒ caption(text))
// no problem!
w[TextView] ~> futureCaption

Part 3

Tooling & documentation

Overview

  • REPL
  • Build system (SBT)
  • IDE support
  • Cloud platforms
  • Where to learn

REPL

Console

scala> def f(n: Int): Int = if (n > 1) {
     |   f(n-1) * n
     | } else {
     |   1
     | }
f: (n: Int)Int

scala> f(5)
res0: Int = 120

Online sandboxes

SBT (info)

Build definition

name := "needs"

organization := "org.needs"

version := "1.0.0-RC3"

scalaVersion := "2.10.3"

libraryDependencies ++= Seq(
  "com.typesafe.play" %% "play-json" % "2.2.0",
  "org.needs" %% "play-functional-extras" % "1.0.0",
  "org.scala-lang.modules" %% "scala-async" % "0.9.0-M4",
  "org.scalatest" %% "scalatest" % "2.0" % "test"
)

...

SBT (info)

Running tasks

sbt
> compile
...
[success] Total time: 7 s, completed 06.03.2014 0:25:55

Rerunning on file change

sbt
> ~test
...
[info] All tests passed.
[success] Total time: 1 s, completed 06.03.2014 0:32:49
1. Waiting for source changes... (press enter to interrupt)

SBT (info)

Plugins for everything

  • Generate IDE project files
  • Code autoformatting
  • Native packaging (.msi, .deb, …)
  • Compile web assets (LESS, CoffeeScript, YUI compressor)
  • git inside sbt console
  • Twitter inside sbt console

IDE support

Scala-IDE (Eclipse plugin)

IDE support

Intellij IDEA

Cloud platforms

  • Heroku (Scala & Play Framework)
  • Cloudbees
  • Could Foundry
  • ...

Learn more