scala101, first steps with scala

49
Scala 101 first steps with Scala Treviso Scala Group - 24th september 2015

Upload: giampaolo-trapasso

Post on 23-Jan-2018

1.598 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Scala101, first steps with Scala

Scala 101first steps with Scala

Treviso Scala Group - 24th september 2015

Page 2: Scala101, first steps with Scala

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

Page 3: Scala101, first steps with Scala

Why do we need a newlanguage?

Page 4: Scala101, first steps with Scala
Page 5: Scala101, first steps with Scala
Page 6: Scala101, first steps with Scala
Page 7: Scala101, first steps with Scala

Well..something happened in last 10~15years

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

Page 8: Scala101, first steps with Scala

The "rise" of the Functional Programming(FP)

functions are used as the fundamental building blocks of aprogramavoids changing-state and mutable datacalling a function f twice with the same value for anargument x will produce the same result f(x)easy scaling in and outmany deep interesting concepts that don't fit a life.. ehm..slide ;)

Page 9: Scala101, first steps with Scala

Scala - Scalable Languageblends Object Oriented and Functional Programmingpowerful static type system (but feels dynamic)concise and expressive syntaxcompiles to Java byte code and runs on the JVMinteroperable with Java itself (both ways!)

Page 10: Scala101, first steps with Scala

Another hipster stuff?Twitter, LinkedIn, FourSquare, Soundcloud, NASA, ..

Functional programming in Scala & Principles of ReactiveProgramming @ Coursera400K online students

http://www.quora.com/What-startups-or-tech-companies-are-using-Scala

Page 11: Scala101, first steps with Scala

Another *USA* hipster stuff?Lambdacon (Bologna) ~ 280 devScala Italy (Milano) ~ 150 + 70Milano Scala Group ~ 570Torino Scala Programming and Big Data Meetup ~ 200G+ Community ~ 90

Page 12: Scala101, first steps with Scala

Show me the code"basic features"

Page 13: Scala101, first steps with Scala

Some feature we'll see/1every value is an objectfunctions are "just" objectscompiler infer types (static typed)(almost) everything is an expressionevery operation is a method call

Page 14: Scala101, first steps with Scala

Some feature we'll see/2language is designed to growcollectionstraitseasy singletonno checked exception (won't see)

Page 15: Scala101, first steps with Scala

Concise syntax - JavaPizza Ipublic 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); }

Page 16: Scala101, first steps with Scala

Concise syntax - JavaPizza/IIpublic 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; }

Page 17: Scala101, first steps with Scala

Concise syntax - JavaPizza/IIIpublic 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; }}

Page 18: Scala101, first steps with Scala

Concise syntax - Pizzaclass Pizza(var tomato: Boolean = true, var cheese: Boolean = true, var ham: Boolean = true, var size: String = "NORMAL")

everything is public by default,use private/protected if neededvar => something you can changeval => something finalspecify defaults if neededtypes are after parameterssetters and getters are generatedmember variables are private (uniform access principle)no semicolon needed

Page 19: Scala101, first steps with Scala

Creating and using objectsval 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 againval newTomato = false // and againval newSize : String = "HUGE"pizza.size = smallSizepizza.tomato = newTomato

Page 20: Scala101, first steps with Scala

Using defaultsval 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 rightyou can pass parameters using names (without order)you can pass only parameters you want using name, ifothers have defaultmore on classes:

cosenonjaviste.it/creare-una-classe-in-scala/

Page 21: Scala101, first steps with Scala

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..

Page 22: Scala101, first steps with Scala

Defining methodsclass 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 defreturn type is optional (with a little exception)Unit ~ void in Javareturn keyword is optional, last expression will bereturneds the string interpolationwhere's the constructor?

Page 23: Scala101, first steps with Scala

Singletons/Iobject Oven { def cook(pizza: Pizza): Unit = { println(s"Pizza $pizza is cooking") Thread.sleep(1000) println("Pizza is ready") }}

a singleton uses the object keywordpattern provided by the languageScala is more OO than Java, no staticplus: a Java class used inside Scala

Page 24: Scala101, first steps with Scala

Singletons/IIobject Margherita extends Pizza(true, true, false, "NORMAL") { override def toString = "Pizza Margherita"}

Oven.cook(Margherita)

objects can extend classesevery overridden method must use override keyword

Page 25: Scala101, first steps with Scala

Case classescase 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 idiomaticval p2 = Pizza(cheese = false) // the same as val p = new Pizza(cheese = false)

syntactic sugar, but super useful and usedevery parameter is immutablea companion object is createdfactory, pattern matching, hashCode, equals, toStringmore on http://cosenonjaviste.it/scala-le-case-class/

Page 26: Scala101, first steps with Scala

Inheritance/Iabstract 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}" }

Page 27: Scala101, first steps with Scala

Inheritance/IIval vito = new Handyman("Vito", 1000)println(vito.greet)vito.preparePizza(Margherita)vito.servePizza(Margherita)

a class can inherit from only one other classa class can mix-in many traitsa trait can extends another one or a classtrait ~ Java 8 interface but have also statestrait linearization resolves the diamond problem

Page 28: Scala101, first steps with Scala

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?

Page 29: Scala101, first steps with Scala

Inheritance/IVabstract 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}

Page 30: Scala101, first steps with Scala

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

Page 31: Scala101, first steps with Scala

Show me the code"advanced features"

Page 32: Scala101, first steps with Scala

Pattern matching/Iobject 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?

Page 33: Scala101, first steps with Scala

Pattern matching/IIa super flexible Java switch (but very different in nature)in love with case classes, but possible on every classcan match partial definition of objectscan match types_ is a wildcard (can throw scala.MatchError without)

Page 34: Scala101, first steps with Scala

Working with collections and functions/Ival 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))

Page 35: Scala101, first steps with Scala

Working with collections and functions/IIeasy to create a collectionfunctions are objects, you can pass them aroundhigh order functionsyou can use methods as functionsfilter, map, fold and all the rest

Page 36: Scala101, first steps with Scala

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

Page 37: Scala101, first steps with Scala

Option/Inull the billion dollar mistakeScala uses Option[T] a trait that encodespresence/absence of valuesNone if there is no value, Some if there some value likeSome(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) }

Page 38: Scala101, first steps with Scala

Option/IIpattern 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!")

null for Java interoperability

Page 39: Scala101, first steps with Scala

Tuplesval bigOrder: (Pizza, Int) = (Pizza(ham = true), 7)

val howMany: Int = bigOrder._2// bigOrder._2 = 4 //don't compile, tuple is immutableval 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 parenthesistuples are immutablezip creates tuple

Page 40: Scala101, first steps with Scala

Implicit conversions/Iclass MargheritaList(val n: Int) {

def margherita = { var list: List[Pizza] = List() for (i <- 1 to n) list = list :+ Margherita list }}

using a var with an immutable listnote the genericsusing collection operator :+List.fill(n)(Margherita) is more idiomaticyou choose how much functional you want to be

Page 41: Scala101, first steps with Scala

Implicit conversions/IIval 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.implicitConversions and importscala.language.postfixOps to get rid of warning or to raise attention

Page 42: Scala101, first steps with Scala

A Pizza DSLval order = 4 margheritaval pizza = order(0) // order headPino commentPizza pizzaOven cook pizzapizza / 6

Question. How much keywords do you see?

Page 43: Scala101, first steps with Scala

For comprehension/ILet's change slice definition

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))}

Page 44: Scala101, first steps with Scala

For comprehension/IIval 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

Page 45: Scala101, first steps with Scala

For comprehension/IIIFor 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

Page 46: Scala101, first steps with Scala

Implicit parameters/Iobject 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 $tip $$"}

val p = new Pizza(tomato = false)Pasquale.receiveOrder(p)Pasquale.prepare(p)Pasquale.serve(p)Pasquale.receivePayment(p, tip = 3)

Page 47: Scala101, first steps with Scala

Implicit parameters/IIwhat's wrong with the previous code?p is 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 for the $tip $$ "}

Page 48: Scala101, first steps with Scala

Implicit parameters/IIIimplicit val p = new Pizza(tomato = false)Pasquale.receiveOrder(p)Pasquale.preparePasquale.servePasquale.receivePayment(tip = 3)

an implicit parameter has nothing special, if you pass it tomethodif it's not provided, compiler will try to find one in scopeif none in scope or more that one, won't compileresolution rules are not so easy, it worth a talk (andactually there's one)

Page 49: Scala101, first steps with Scala

The endQ & Option[A]

Thanks for following, slides and code on, Twitter or LinkedInhttps://github.com/giampaolotrapasso/