2. Hello, my name is...
Giampaolo Trapasso
(there aren't enough heros these days!)
@supergiampaolo
(ask for a sticker!)
cosenonjaviste.it
(have a blog? do a PR!)
blogzinga.it
7. Well..something happened in last 10~15
years
Cores 1 → 2 → 4 → ...
Server nodes 1 → 10's → 1000’s.
Response times seconds → milliseconds
Maintenance downtimes hours → nones
Data volum GBs → TBs and more
8. The "rise" of the Functional Programming
(FP)
functions are used as the fundamental building blocks of a
program
avoids changing-state and mutable data
calling a function f twice with the same value for an
argument x will produce the same result f(x)
easy scaling in and out
many deep interesting concepts that don't fit a life.. ehm..
slide ;)
9. Scala - Scalable Language
blends Object Oriented and Functional Programming
powerful static type system (but feels dynamic)
concise and expressive syntax
compiles to Java byte code and runs on the JVM
interoperable with Java itself (both ways!)
10. Another hipster stuff?
Twitter, LinkedIn, FourSquare, Soundcloud, NASA, ..
Functional programming in Scala & Principles of Reactive
Programming @ Coursera
400K online students
http://www.quora.com/What-startups-or-tech-
companies-are-using-Scala
11. Another *USA* hipster stuff?
Lambdacon (Bologna) ~ 280 dev
Scala Italy (Milano) ~ 150 + 70
Milano Scala Group ~ 570
Torino Scala Programming and Big Data Meetup ~ 200
G+ Community ~ 90
13. Some feature we'll see/1
every value is an object
functions are "just" objects
compiler infer types (static typed)
(almost) everything is an expression
every operation is a method call
14. Some feature we'll see/2
language is designed to grow
collections
traits
easy singleton
no checked exception (won't see)
15. Concise syntax - JavaPizza I
public class JavaPizza {
private Boolean tomato = true;
private Boolean cheese = true;
private Boolean ham = true;
private String size = "NORMAL";
public JavaPizza(Boolean tomato, Boolean cheese,
Boolean ham, String size) {
this.setTomato(tomato);
this.setCheese(cheese);
this.setHam(ham);
this.setSize(size);
}
16. Concise syntax - JavaPizza/II
public Boolean getTomato() {
return tomato;
}
public void setTomato(Boolean tomato) {
this.tomato = tomato;
}
public Boolean getCheese() {
return cheese;
}
public void setCheese(Boolean cheese) {
this.cheese = cheese;
}
17. Concise syntax - JavaPizza/III
public Boolean getHam() {
return ham;
}
public void setHam(Boolean ham) {
this.ham = ham;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
18. Concise syntax - Pizza
class Pizza(var tomato: Boolean = true,
var cheese: Boolean = true,
var ham: Boolean = true,
var size: String = "NORMAL")
everything is public by default,
use private/protectedif needed
var=> something you can change
val=> something final
specify defaults if needed
types are after parameters
setters and getters are generated
member variables are private (uniform access principle)
no semicolon needed
19. Creating and using objects
val pizza = new Pizza(true, false, true, "HUGE") // type inference
is the same as
val pizza : Pizza = new Pizza(true, false, true, "HUGE")
val smallSize = "SMALL" // type inference again
val newTomato = false // and again
val newSize : String = "HUGE"
pizza.size = smallSize
pizza.tomato = newTomato
20. Using defaults
val pizza1 = new Pizza(true, true, false, "NORMAL")
val pizza2 = new Pizza(true, true)
val pizza3 = new Pizza(tomato = true, ham = true, size = "HUGE", cheese =
val pizza4 = new Pizza(size = "SMALL")
if parameters have default, you can omit them on right
you can pass parameters using names (without order)
you can pass only parameters you want using name, if
others have default
more on classes:
cosenonjaviste.it/creare-una-classe-in-scala/
21. Nobody loves mutable pizzas!
In the following, we'll use only immutable pizzas
class Pizza(val tomato: Boolean = true,
val cheese: Boolean = true,
val ham: Boolean = true,
val size: String = "NORMAL")
Think about how much Java code you saved..
22. Defining methods
class Pizza(val tomato: Boolean = true,
val cheese: Boolean = true,
val ham: Boolean = true,
val size: String = "NORMAL"){
def slice(numberOfPieces: Int): Unit = {
println(s"Pizza is in ${numberOfPieces} pieces")
}
}
a method starts with a def
return type is optional (with a little exception)
Unit~ voidin Java
returnkeyword is optional, last expression will be
returned
sthe string interpolation
where's the constructor?
23. Singletons/I
object Oven {
def cook(pizza: Pizza): Unit = {
println(s"Pizza $pizza is cooking")
Thread.sleep(1000)
println("Pizza is ready")
}
}
a singleton uses the objectkeyword
pattern provided by the language
Scala is more OO than Java, no static
plus: a Java class used inside Scala
24. Singletons/II
object Margherita extends Pizza(true, true, false, "NORMAL") {
override def toString = "Pizza Margherita"
}
Oven.cook(Margherita)
objects can extend classes
every overridden method must use overridekeyword
25. Case classes
case class Pizza(tomato: Boolean = true,
cheese: Boolean = true,
ham: Boolean = true,
size: String = "NORMAL") {
def slice(numberOfPieces: Int): Unit = {
println(s"Pizza is in ${numberOfPieces} pieces")
}
}
val p1 = Pizza.apply(cheese = false) // not idiomatic
val p2 = Pizza(cheese = false)
// the same as val p = new Pizza(cheese = false)
syntactic sugar, but super useful and used
every parameter is immutable
a companion object is created
factory, pattern matching, hashCode, equals, toString
more on http://cosenonjaviste.it/scala-le-case-class/
26. Inheritance/I
abstract class Worker(val name: String){
def greet : String // this is abstract
}
trait PizzaMaker{
def preparePizza(pizza: Pizza) = println(s"I prepare ${pizza}")
}
trait Waiter{
def servePizza(pizza: Pizza) = println(s"this is your ${pizza}")
}
class Handyman(override val name: String, val wage: Int)
extends Worker(name) with PizzaMaker with Waiter {
override def greet: String = s"Hello, I'm ${name}"
}
27. Inheritance/II
val vito = new Handyman("Vito", 1000)
println(vito.greet)
vito.preparePizza(Margherita)
vito.servePizza(Margherita)
a class can inherit from only one other class
a class can mix-in many traits
a trait can extends another one or a class
trait ~ Java 8 interface but have also states
trait linearization resolves the diamond problem
28. Inheritance/III (diamond)
abstract class Worker(val name: String){
def greet : String // this is abstract
}
trait PizzaMaker extends Worker{
def preparePizza(pizza: Pizza) = println(s"I prepare ${pizza}")
override def greet = "Hello"
}
trait Waiter extends Worker {
def servePizza(pizza: Pizza) = println(s"this is your ${pizza}")
override def greet = "How can I serve you?"
}
class Handyman(override val name: String, val wage: Int)
extends Worker(name) with Waiter with PizzaMaker
What will print vito.greet?
29. Inheritance/IV
abstract class Worker(val name: String){
def greet : String // this is abstract
}
trait PizzaMaker {
def preparePizza(pizza: Pizza) = println(s"I prepare ${pizza}")
def greet = "Hello"
}
trait Waiter {
def servePizza(pizza: Pizza) = println(s"this is your ${pizza}")
def greet = "How can I serve you?"
}
class Handyman(override val name: String, val wage: Int) extends Worker(name)
override def greet = super[Waiter].greet
}
30. Inheritance/V (Compile error!)
abstract class Worker(val name: String){
def greet : String // this is abstract
}
class Intern
trait PizzaMaker extends Intern {
def greet = "Hello"
}
trait Waiter extends Worker{
def greet = "How can I serve you?"
}
class Handyman(override val name: String, val wage: Int)
extends Worker(name) with Waiter with PizzaMaker
32. Pattern matching/I
object Pino {
def comment(pizza: Pizza) =
pizza match {
case Pizza(t, c, h, s) if (s == "HUGE") => "Wow!"
case Pizza(false, cheese, ham, size) =>
s"No tomato on this ${size} pizza"
case Pizza(false, _, _, "SMALL") =>
"Little champion, your white pizza is coming"
case pizza@Margherita =>
s"I like your ${pizza.size} Margherita"
case _ => "OK"
}
}
third case won't fire, why?
33. Pattern matching/II
a super flexible Java switch(but very different in nature)
in love with case classes, but possible on every class
can match partial definition of objects
can match types
_is a wildcard (can throw scala.MatchErrorwithout)
34. Working with collections and functions/I
val order: List[Pizza] = List(pizza1, pizza2, pizza3, pizza4)
val noTomato: (Pizza => Boolean) = (p => p.tomato == false)
order
.filter(noTomato)
.filter(p => p.ham == true)
.map(pizza => Pino.comment(pizza))
35. Working with collections and functions/II
easy to create a collection
functions are objects, you can pass them around
high order functions
you can use methods as functions
filter, map, fold and all the rest
36. Operators are just methods (an example)
case class Pizza(tomato: Boolean = true, cheese: Boolean = true,
ham: Boolean = true, size: String = "NORMAL"){
def slice(numberOfPieces: Int) =
s"Pizza is in ${numberOfPieces} pieces"
def /(numberOfPieces: Int) = slice(numberOfPieces)
}
val pizza = Pizza()
pizza.slice(4)
pizza./(4)
pizza / 4
Simple rules to simplify syntax
37. Option/I
nullthe billion dollar mistake
Scala uses Option[T]a trait that encodes
presence/absence of values
Noneif there is no value, Someif there some value like
Some(42)
caller if forced to handle the case
object TheLazyPizzaMaker {
def prepare(p: Pizza): Option[Pizza] =
if (Random.nextInt(6) == 0) None
else Some(p)
}
38. Option/II
pattern matching to handle an Option
val result = TheLazyPizzaMaker.prepare(Margherita)
result match {
case Some(p) => "My pizza is ready"
case None => "Fire that pizza maker!"
}
option as a list with at most one value
result.map(o => "My pizza is ready").getOrElse("Fire that pizza maker!")
nullfor Java interoperability
39. Tuples
val bigOrder: (Pizza, Int) = (Pizza(ham = true), 7)
val howMany: Int = bigOrder._2
// bigOrder._2 = 4 //don't compile, tuple is immutable
val newBigOrder = bigOrder.copy(_2 = 4)
val number = List(3, 4, 2, 1)
val hugeOrder: List[(Pizza, Int)] = order.zip(number)
//List((Pizza(true,true,false,NORMAL),3), (Pizza(true,true,true,NORMAL),4)...
val hugeOrder2 = hugeOrder.map(t => t.swap)
to create a tuple, just open a parenthesis
tuples are immutable
zipcreates tuple
40. Implicit conversions/I
class MargheritaList(val n: Int) {
def margherita = {
var list: List[Pizza] = List()
for (i <- 1 to n)
list = list :+ Margherita
list
}
}
using a varwith an immutable list
note the generics
using collection operator :+
List.fill(n)(Margherita)is more idiomatic
you choose how much functional you want to be
41. Implicit conversions/II
val order = new MargheritaList(4).margherita()
a bit verbose..let's introduce a implicit conversion
implicit def fromIntToMargherita(n: Int) = new MargheritaList(n)
compiler implicity does conversion for us
val order = 4.margherita
or better
val order = 4 margherita
Hint: use import scala.language.implicitConversionsand import
scala.language.postfixOpsto get rid of warning or to raise attention
42. A Pizza DSL
val order = 4 margherita
val pizza = order(0) // order head
Pino commentPizza pizza
Oven cook pizza
pizza / 6
Question. How much keywords do you see?
43. For comprehension/I
Let's change slicedefinition
case class Slice(p: Pizza, fractions: Int) {
override def toString = s"1/$fractions of $p"
}
case class Pizza(tomato: Boolean = true,
cheese: Boolean = true,
ham: Boolean = true,
size: String = "NORMAL") {
def slice(n: Int): List[Slice] = List.fill(n)(Slice(this, n))
}
44. For comprehension/II
val order = List(Pizza(), Pizza(ham = false))
How to get the list of every slice description?
val list = order.map(p => p.slice(4)) // List[List[Slice]] is wrong
val slices = order.flatMap(p => p.slice(4)) // List[Slice]
val descriptions = listOfSlices.map(slice => slice.toString)
or
val descriptions = order.flatMap(p => p.slice(4)).map(slice => slice.toString
45. For comprehension/III
For comprehension may be more readable
val descriptions = for { pizza <- order
slice <- pizza.slice(4)
} yield slice.toString
than
val descriptions = order.flatMap(p => p.slice(4)).map(slice => slice.toString
for comprehension is different from for loop (no yield)
is purely syntactic sugar
46. Implicit parameters/I
object Pasquale {
def prepare(p: Pizza) = s"I prepare you pizza $p"
def receiveOrder(p: Pizza) = s"You ordered me $p"
def serve(p: Pizza) = s"Here is your pizza $p"
def receivePayment(p: Pizza, tip: Int) = s"Thanks for paying $p and for the $ti
}
val p = new Pizza(tomato = false)
Pasquale.receiveOrder(p)
Pasquale.prepare(p)
Pasquale.serve(p)
Pasquale.receivePayment(p, tip = 3)
47. Implicit parameters/II
what's wrong with the previous code?
pis something like a context (think to a DB connection)
implicit parameters solve this kind of problem
object Pasquale {
def prepare(implicit p: Pizza) = s"I prepare you pizza $p"
def receiveOrder(implicit p: Pizza) = s"You ordered me $p"
def serve(implicit p: Pizza) = s"Here is your pizza $p"
def receivePayment(tip: Int)(implicit p: Pizza) = s"Thanks for paying $p and fo
}
48. Implicit parameters/III
implicit val p = new Pizza(tomato = false)
Pasquale.receiveOrder(p)
Pasquale.prepare
Pasquale.serve
Pasquale.receivePayment(tip = 3)
an implicit parameter has nothing special, if you pass it to
method
if it's not provided, compiler will try to find one in scope
if none in scope or more that one, won't compile
resolution rules are not so easy, it worth a talk (and
actually there's one)
49. The end
Q & Option[A]
Thanks for following, slides and code on
, Twitter or LinkedInhttps://github.com/giampaolotrapasso/