On fait la Java dans – Scala – Scala de Milan ?



On fait la Java dans – Scala – Scala de Milan ?

0 1


scala-prez


On Github avandendaele / scala-prez

On fait la Java dans

Scala

Créé par Adrien Cominotto [≡] / Alexis Vandendaele [≡]

Scala de Milan ?

Non celui de l'EPFL

Créé par Martin Odersky en 2003

Son nom vient de l'anglais Scalable language

Scala intègre les paradigmes de programmation orientée objet et de programmation fonctionnelle, avec un typage statique

Pourquoi Scala ?

public class Person {
    private final String name;
    private final String firstName;
    public Person(String name, String firstName) {
        this.name = name;
        this.firstName = firstName;
    }
    public String getName() {
        return name;
    }
    public String getFirstName() {
        return firstName;
    }
}
class Person(val name: String, val firstName: String)

Acte premier

Les bases

  • les String interpolées
  • les classes
  • les objects
  • les traits
  • les tuples

Les Strings interpolées

Keep It Simple, Stupid

val height = 1.9d
val name = "James"

println(s"Hello, $name")
println(s"1 + 1 = ${1 + 1}")

println(f"$name%s is $height%.2f meters tall")

Les classes

C'est la Class

class Person(val name: String, val firstName: String) {
    override def toString = s"[name=$name, firstname=$firstName]"
}

val p = new Person("Odersky", "Martin")

Les objects

et plus si affinités ...

class Person(val name: String, val firstName: String) {
    override def toString = s"[name=$name, firstname=$firstName]"
}

object Person { // Companion object
    def apply(name: String, firstName: String) = new Person(name, firstName)
    val all = List( Person("Odersky", "Martin"), 
                    Person("Kuhn", "Roland"), 
                    Person("Suereth","Josh"))
}

val vips = Person.all

Les case classes

Sans passer par la case boilerplate

class Person(val name: String, val firstName: String) {
    override def toString = s"[name=$name, firstname=$firstName]"
}
case class Person(val name: String, val firstName: String)

val p = Person("Odersky", "Martin")

Les traits

L'union de l'abstrait et des interfaces

class Animal {
     override def toString = "I'm an animal"
}

trait Flying extends Animal {
     override def toString = s"${super.toString} and I fly"
}

trait Swimming extends Animal {
     override def toString = s"${super.toString} and I swim"
}

val swimmingBird = new Animal with Flying with Swimming
val flyingFish = new Animal with Swimming with Flying

Les tuples

Des structures rapides et faciles

val t = ("Alexis", 29) // Tuple2
t._1 // Premier membre
t._2 // Second membre

Acte second

Le fonctionnel basique

  • L'Immutabilité
  • Les fonctions sont des objets ?!
  • Le pattern matching
  • L'exemple avec Option[T]

L'immutabilité

  • Avantages
    • Thread-Safe
    • Transparence référentielle
  • Désavantages
    • Pas simple à mettre en place dans un environnement où les objets contiennent des états

Les fonctions sont des objets ?!

def profile(arg: Int, fct: Int => Int) = {
    val r = fct(arg)
    println(s"value = $r")
    r
}

val add42 = {i: Int => i + 42}

profile(3, add42)

Pattern Matching

Switch, Allez à la case départ

def parseArg(arg: String) = arg match {
    case "--help" | "-h" => println("Afficher l'aide")
    case "--version" | "-v" => println("Afficher la version")
    case unknownArg => println(s"Argument non reconnu: $unknownArg")
}

Leveled Up

case class MyClass(a: Int, b: String)

MyClass(scala.util.Random.nextInt(100), "foo") match {
    case MyClass(42, s) => println("Bravo! $s,  tu as trouvé la réponse!")
    case MyClass(n, "foo") if n < 42 => println(s"$n, trop bas");
    case MyClass(n, "foo") if n > 42 => println(s"$n trop haut");
    case MyClass(n, s) => println(s"Désolé $s, $n n'est pas la réponse")
}

Catch me if you can

case class FooException(msg: String) extends RuntimeException(msg)

try {
    throw FooException("bar")
} catch {
    case FooException(msg) => println(s"Exception $msg")
    case e: RuntimeException =>
        println("RuntimeException catched and rethrown")
        throw e
    case scala.util.control.NonFatal(e) =>
        println("Something not that bad occured")
        throw e
}

Option[T]

To Be or Not To Be ...

val foo = Option(42)
foo match {
     case Some(v) => println(v)
     case None => println("Whoops, nothing...")
}

Acte trois

Les collections

  • filter
  • map
  • flatMap
  • La for comprehension
  • foldLeft

filter

List[T] filter(f: T => Boolean): List[T]
speakers.filter(s => s.age <= 25)

map

List[T] map[U](f: T => U): List[U]
speakers.map(s => s.name + " " + s.firstName)

flatMap

List[T] flatMap[U](f: T => List[U]): List[U]
speakers.flatMap(s => s :: imaginaryChildren)

La for comprehension

Le couteau suisse

for {
    s <- speakers
    ic <- imaginaryChildren if (ic.name == s.name)
} yield (s, ic)
speakers.flatMap{s => imaginaryChildren
    .filter(_.name == s.name)
    .map(ic => (s, ic))
}

foldLeft

List[T] foldLeft[U](acc: U)(f: (U, T) => U): U
val l = List(1,2,3)
l.foldLeft(""){ (acc, e) => acc + e }
persons.foldLeft((0,0)) { (acc, p) => p.sex match {
         case Female => (acc._1 + 1, acc._2)
         case Male => (acc._1, acc._2 + 1)
         case _ => acc
     }
}

Acte quatre

Les implicites

Les implicites

implicit val x = 5
def inc(implicit i: Int) = i + 1
case class Person(age: Int, name: String) {
    def sayHi = println(s"Hi!, I'm $name and I'm $age")
}
implicit def tupleToPerson(t: (Int, String)): Person = {
    Person(t._1, t._2)
}
(29, "Alexis").sayHi
def sorted[A] (implicit ord: math.Ordering[A]): List[A]
implicit object AgeOrdering extends Ordering[Person] {
     def compare(a: Person, b: Person) = a.age compare b.age
}
person.sorted

Acte cinq

L'asynchrone

La promesse d'un future radieux

  • Les Futures
  • Les Promises

Le problème

val socket = Socket()
val paquet = socket.readFromMemory()
socket.sendToUSA(paquet)

Temps d'executions

execute typical instruction 1 nanosec fetch from main memory 100 nanosec send 2K bytes over 1Gbps network 20,000 nanosec read 1MB sequentially from memory 250,000 nanosec fetch from new disk location (seek) 8,000,000 nanosec read 1MB sequentially from disk 20,000,000 nanosec send packet US to Europe and back 150,000,000 nanosec source: Peter Norvig

Le problème

val socket = Socket()
val paquet = socket.readFromMemory() // 250 000 ns
socket.sendToUSA(paquet) // 150 000 000 ns

1 nanoseconde = 1 seconde

val socket = Socket()
val paquet = socket.readFromMemory() // 3 jours
socket.sendToUSA(paquet) // 5 ans

Les Futures

Future[T]
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

val socket = Socket()
val paquet = Future { socket.readFromMemory()  }
paquet.map(socket.sendToUSA)
for {
    paquet <- Future{ socket.readFromMemory() }
} yield socket.sendToUSA(paquet)

Les Promises

Promise[T]().future
import scala.concurrent._
import ExecutionContext.Implicits.global

val promise = Promise[String]()
val first = for(first <- promise.future) yield (s"$first FIRST!")

def sendToUsa(message: String) = Future {
    Thread.sleep(scala.util.Random.nextInt(5000))
    message
}.map(m => promise.success(s"USA received $m"))

def sendToChina(message: String) = Future {
    Thread.sleep(scala.util.Random.nextInt(5000))
    message
}.map(m => promise.success(s"China received $m"))

sendToUsa("Hello!"); sendToChina("Ni hao!")

Quand je suggère l’usage de nouvelles technos

source: Les joies du code

Des questions ?

Non ? Dans scala allez plus loin