scala - java2days sofia
DESCRIPTION
This is a short introduction to the Scala programming language and its ecosystem, giving some background about how the language came to be and a quick taste of what it looks like. It also shortly introduces a few tools and technologies related to itTRANSCRIPT
SCALAJava2Days 2013
Manuel Bernhardt
Dienstag, 03. Dezember 13
@elmanu
AGENDA
• History
• Why Scala?
• Scala in the wild
• The Code / Scala in practice
• Tools & more
Dienstag, 03. Dezember 13
@elmanu
YOUR SPEAKER
• Independent software consultant based in Vienna
• Web, web, web
• Scala & Java & Javascript
• Open-Source
Dienstag, 03. Dezember 13
@elmanu
AGENDA
• History
• Why Scala?
• Scala in the wild
• The Code / Scala in practice
• Tools & more
Dienstag, 03. Dezember 13
@elmanu
HISTORY
• Martin Odersky, EPFL
• Espresso, Pizza, GJ, javac
• Funnel, Scala
• First Scala release in 2003
Dienstag, 03. Dezember 13
@elmanu
AGENDA
• History
• Why Scala?
• Scala in the wild
• The Code / Scala in practice
Dienstag, 03. Dezember 13
@elmanu
SCALA DESIGN GOALS
Dienstag, 03. Dezember 13
@elmanu
SCALA DESIGN GOALS
• Full interoperability with Java
Dienstag, 03. Dezember 13
@elmanu
SCALA DESIGN GOALS
• Full interoperability with Java
• Cut down boilerplate
Dienstag, 03. Dezember 13
@elmanu
SCALA DESIGN GOALS
• Full interoperability with Java
• Cut down boilerplate
• Pure object orientation & functional programming
Dienstag, 03. Dezember 13
@elmanu
SCALA DESIGN GOALS
• Full interoperability with Java
• Cut down boilerplate
• Pure object orientation & functional programming
• Move away from null
Dienstag, 03. Dezember 13
@elmanu
SCALA DESIGN GOALS
• Full interoperability with Java
• Cut down boilerplate
• Pure object orientation & functional programming
• Move away from null
• Multi-core programming
Dienstag, 03. Dezember 13
@elmanu
AGENDA
• History
• Why Scala?
• Scala in the wild
• The Code / Scala in practice
• Tools & more
Dienstag, 03. Dezember 13
@elmanu
WHAT PEOPLE SAY
If I were to pick a language todayother than Java, it would be Scala.
James GoslingFather of Java
Dienstag, 03. Dezember 13
@elmanu
WHAT PEOPLE SAY
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 StrachanCreator of Groovy
http://macstrac.blogspot.co.at/2009/04/scala-as-long-term-replacement-for.html
Dienstag, 03. Dezember 13
@elmanu
ThoughtWorks TechRadar May 2013http://www.thoughtworks.com/radar
Dienstag, 03. Dezember 13
@elmanu
ThoughtWorks TechRadar May 2013http://www.thoughtworks.com/radar
Dienstag, 03. Dezember 13
@elmanu
SCALA IN THE WILD
etc.
Dienstag, 03. Dezember 13
@elmanu
SCALA IN THE WILD
Dienstag, 03. Dezember 13
@elmanu
SCALA IN THE WORLD
http://www.scala-tribes.org/Dienstag, 03. Dezember 13
@elmanu
SCALA IN VIENNA
• Scala Vienna User Group
• 1 year old, 124+ members
• http://scala-vienna.org/
Dienstag, 03. Dezember 13
@elmanu
AGENDA
• History
• Why Scala?
• Scala in the wild
• The Code / Scala in practice
• Tools & more
Dienstag, 03. Dezember 13
@elmanu
AVOIDING THE BILLION-DOLLAR MISTAKE
But I couldn't resist the temptation to put in a null
reference, simply because it was so easy to implement
Tony Hoare Creator of ALGOL
Dienstag, 03. Dezember 13
@elmanu
AVOIDING THE BILLION- DOLLAR MISTAKE
val maybeUser: Option[User] = User.findOneByName("bob")// returns Some[User]
maybeUser == None // false
maybeUser.foreach { user => println(user.fullName) // prints "Bob Marley" if there is a user!}
val name = maybeUser.map(_.name).getOrElse("Unknown user")
Dienstag, 03. Dezember 13
@elmanu
CONCISENESSpublic class User {
! private String name;
! private String surname;
! private String email;
! public User(String name, String surname, String email) {! ! this.name = name;! ! this.surname = surname;! ! this.email = email;! }
! public void setName(String name) {! ! this.name = name;! }
! public void setSurname(String surname) {! ! this.surname = surname;! }
! public void setEmail(String email) {! ! this.email = email! }
! public String getName() {! ! return this.name;! }
! public String getSurname() {! ! return this.surname;! }
! public String getEmail() {! ! return this.surname;! }
}
Dienstag, 03. Dezember 13
@elmanu
CONCISENESSclass User( var name: String, var surname: String, var email: String)
val bob = new User("Bob", "Marley", "[email protected]")// bob: User = User@5c3f1224
bob.name // res0: String = Bob
bob.name = "Bobby" // bob.name: String = Bobby
Dienstag, 03. Dezember 13
@elmanu
CONCISENESSpublic class ImmutableUser {
! private final String name;
! private final String surname;
! private final String email;
! public ImmutableUser(String name, String surname, String email) {! ! this.name = name;! ! this.surname = surname;! ! this.email = email;! }
! public String getName() {! ! return this.name;! }
! public String getSurname() {! ! return this.surname;! }
! public String getEmail() {! ! return this.surname;! }
! @Override public int hashCode() {
! ! // yada yada yada! }
! @Override public boolean equals(Object that) {
! ! // yada yada yada
! }
}
Dienstag, 03. Dezember 13
@elmanu
CONCISENESScase class ImmutableUser( name: String, surname: String, email: String)
val bob = ImmutableUser("Bob", "Marley", "[email protected]")// hashcode and equals for free!
val namedBob = ImmutableUser(name = "Bob", surname = "Marley", email = "email")
val bobby = bob.copy(name = "Bobby") // returns a User with name Bobby
bob.toString // res0: String = ImmutableUser(Bob,Marley,email)
Dienstag, 03. Dezember 13
@elmanu
USEFUL TYPE INFERENCE
Dienstag, 03. Dezember 13
@elmanu
USEFUL TYPE INFERENCEval foo = "Bar" // foo: String = Bar
val answer = 42 // answer: Int = 42
val price = 9.99 // price: Double = 9.99
val nums = List(1, 2, 3) // nums: List[Int] = List(1, 2, 3)
val map = Map("abc" -> List(1, 2, 3))// map: scala.collection.immutable.Map[String,List[Int]] = Map(abc -> List(1, 2, 3))
Dienstag, 03. Dezember 13
@elmanu
EXPLICIT TYPINGval foo: String = "Bar" // foo: String = Bar
val answer: Int = 42 // answer: Int = 42
val price: Double = 9.99 // price: Double = 9.99
val nums: List[Int] = List(1, 2, 3) // nums: List[Int] = List(1, 2, 3)
val map: Map[String, List[Int]] = Map("abc" -> List(1, 2, 3))// map: scala.collection.immutable.Map[String,List[Int]] = Map(abc -> List(1, 2, 3))
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLEusers.sort(new Comparator { public int compare(Object user1, Object user2) { ! int userAge1 = ((User) user1).getAge(); ! int userAge2 = ((User) user2).getAge(); ! if (userAge1 > userAge2) { ! ! return 1; ! } else if userAge1 < userAge2) {! ! ! return -1;! ! } else {! ! ! return 0;! ! }
! }});
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLE
def sortByAge(user1: User, user2: User) = user1.age > user2.age
users.sortWith(sortByAge)
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLE
users.sortWith((user1, user2) => user1.age > user2.age)
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLE
users.sortWith(_.age > _.age)
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLE
List<User> minors = new ArrayList<User>();List<User> majors = new ArrayList<User>();
for (User u : users) {! if (u.getAge() < 18) {! ! minors.add(u);! } else {! ! majors.add(u);! }}
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLE
val (minors, majors) = users.partition(_.age < 18)
Dienstag, 03. Dezember 13
@elmanu
COLLECTION LIBRARY & FUNCTIONAL STYLE
val minors = users.filter(_.age < 18)
Dienstag, 03. Dezember 13
@elmanu
• Minimal language, powerful library
• Language features for extensibility
EXTENSIBLE LANGUAGE
Dienstag, 03. Dezember 13
@elmanu
DOMAIN SPECIFIC LANGUAGES
import collection.mutable.Stackimport org.scalatest._
class ExampleSpec extends FlatSpec with Matchers {
"A Stack" should "pop values in last-in-first-out order" in { val stack = new Stack[Int] stack.push(1) stack.push(2) stack.pop() should be (2) stack.pop() should be (1) }
it should "throw NoSuchElementException if an empty stack is popped" in { val emptyStack = new Stack[Int] a [NoSuchElementException] should be thrownBy { emptyStack.pop() } }}
Dienstag, 03. Dezember 13
@elmanu
DOMAIN SPECIFIC LANGUAGES
import collection.mutable.Stackimport org.scalatest._
class ExampleSpec extends FlatSpec with Matchers {
"A Stack" should "pop values in last-in-first-out order" in { val stack = new Stack[Int] stack.push(1) stack.push(2) stack.pop() should be (2) stack.pop() should be (1) }
it should "throw NoSuchElementException if an empty stack is popped" in { val emptyStack = new Stack[Int] a [NoSuchElementException] should be thrownBy { emptyStack.pop() } }}
Dienstag, 03. Dezember 13
@elmanu
MACROS
• Compile-time, during type checking
• Expanding the AST
• Experimental since Scala 2.10
http://scalamacros.org
Dienstag, 03. Dezember 13
@elmanu
MACROSPLAY JSON DE/SERIALIZATION
Dienstag, 03. Dezember 13
@elmanu
MACROSPLAY JSON DE/SERIALIZATION
case class Creature(name: String, isDead: Boolean, weight: Float)
implicit val creatureReads: Reads[Creature] = ( (__ \ "name").read[String] and (__ \ "isDead").read[Boolean] and (__ \ "weight").read[Float])(Creature)
implicit val creatureWrites: Writes[Creature] = ( (__ \ "name").write[String] and (__ \ "isDead").write[Boolean] and (__ \ "weight").write[Float])(unlift(Creature.unapply))
Dienstag, 03. Dezember 13
@elmanu
MACROSPLAY JSON DE/SERIALIZATION
import play.api.json._
implicit val creatureFormat = Json.format[Creature] // format is a macro
Dienstag, 03. Dezember 13
@elmanu
AGENDA
• History
• Why Scala?
• Scala in the wild
• The Code / Scala in practice
• Tools & more
Dienstag, 03. Dezember 13
@elmanu
IDE
• IntelliJ IDEA
• Eclipse
• SublimeText
Dienstag, 03. Dezember 13
@elmanu
SIMPLE BUILD TOOLname := "My Project"
version := "1.0"
organization := "org.myproject"
libraryDependencies += "org.scala-tools.testing" %% "scalacheck" % "1.8" % "test"
libraryDependencies ++= Seq( "net.databinder" %% "dispatch-meetup" % "0.7.8", "net.databinder" %% "dispatch-twitter" % "0.7.8")
javaOptions += "-Xmx256m"
logLevel in compile := Level.Warn
Dienstag, 03. Dezember 13
@elmanu
PLAY! FRAMEWORK
• MVC web framework, inspired by RoR and Django
• Java, Scala
• Everything is compiled
• Predictable & scalable performance
• Fun to work with!
Dienstag, 03. Dezember 13
@elmanu
PLAY! FRAMEWORK
• MVC web framework, inspired by RoR and Django
• Java, Scala
• Everything is compiled
• Predictable & scalable performance
• Fun to work with!
Dienstag, 03. Dezember 13
@elmanu
AKKA
• Toolkit for building concurrent & distributed applications more easily
• Actors as concurrency model, simpler to reason with than threads
• Remoting and clustering support
Dienstag, 03. Dezember 13
REACTIVE
http://www.reactivemanifesto.org
Dienstag, 03. Dezember 13
@elmanu
THANK YOU!
Questions, comments ?http://manuel.bernhardt.io
@elmanu
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: AKKA
• Actor concurrency model based on Erlang
• “Human” design: actors talk to eachother and form hierarchies
• Much, much, much simpler to work and reason with than threads
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: AKKA
Source: http://prabhubuzz.wordpress.com/2012/09/28/akka-really-mountains-of-concurrency/
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: AKKAclass Master extends Actor {
! val workers = context.actorOf(Props[Worker].withRouter( ! RoundRobinRouter(nrOfInstances = 5))! )
! def receive = {
! ! case Start =>! ! ! getDocumentsFromDb.foreach { document =>! ! ! ! workers ! Process(document)! ! ! }
! ! case Result(processed) =>! ! ! writeResult(processed)
! ! case Stop =>! ! ! children.foreach(stop)
! }}
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: AKKA
class Worker extends Actor {
! def receive = {
! ! case Process(doc: Document) =>! ! ! val processed = doSomeHardWork(doc)! ! ! sender ! Result(processed)! }
}
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: PLAY
• MVC framework à la Rails
• Everything is compiled
• I mean everything: CSS, JavaScripts, Templates, URLs, JSON, ...
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: PLAY
GET /users controllers.Users.listPOST /users controllers.Users.createPUT /users/:id/update controllers.Users.update(id: Long)DELETE /users/:id controllers.Users.delete(id: Long)
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: PLAY
class Users extends Controller {
def list = Action { request => val users = User.findAll Ok(Json.toJson(users)) }
}
Dienstag, 03. Dezember 13
@elmanu
FRAMEWORKS: PLAY
class Users extends Controller {
def list = Action { request => val users = User.findAll Ok(Json.toJson(users)) }
}200 OK
Content-Type: application/json
Dienstag, 03. Dezember 13