Két Java fejlesztő első Scala
projektje
Szabó Szilárd,Sörös Soma - switchedOn,DPC
HOUG Szakmai nap 2015.10.07
Agenda
● Mi is az a Scala
● Miért pont a Scala?
● Kezdeti nehézségek
● Pro és Kontra ( Scala vs. Java 8 )
Mi is az a Scala?
● “Scalable Language”
● Néhány embernek olyan mint egy script nyelv
– tömör
– nincs útban típusosság
– REPL, IDE “worksheet”-ek segítik a gyors visszajelzést
● Másoknak kedvelt nyelv a mission critical szerver rendszerek fejlesztéséhez.
– Használók: Twitter, LinkedIn, Intel és sokan mások
Mi is az a Scala? - Kezdetben
● Java pontos-vesszők nélkül:
– Hello world:
– JVM-ben fut
– Objektum Orientált
– Teljes mértékű interoperabilitás a Java nyelvvel
● Szabadon kombinálhatóak a Java és Scala osztályok akár egy projekten belül
object HelloWorld {
def main(args: Array[String]) {
println( "Hello, world!" )
}
}
Mi is az a Scala? - OO és Funkcionális
● Objektum-orientált funkcionális
programozási nyelv
– a függvények egyszerű
objektumok
object UnifiedTypes {
def hello(arg:String) = s "Hello, $arg!"
val list = List( "Egy string" , 732,'c',true,hello _)
println(list)
//> List(Egy string, 732, c, true, <function1>)
println(hello( "Kozonseg")) //> Hello, Kozonseg!
val function = list(4)
.asInstanceOf[Function[String,String]]
function( "Kozonseg") //> Hello, Kozonseg!
}
Mi is az a Scala? - Unified types
● Objektum-orientált funkcionális
programozási nyelv
– a függvények egyszerű
objektumok
– unified types
Mi is az a Scala? - Pattern matching
● Objektum-orientált funkcionális
programozási nyelv
– a függvények egyszerű
objektumok
– unified types
– pattern matching
def matcher(x:Any) = x match {
case 1 => "one"
case _:Int => "Other integer"
case h::t => s "List with $h"
case h::t if h == 1 => s "First element is one"
case Person(first,last) => s "Hello, $first!"
case _ => "Nothing else matched"
} //> matcher: (x: Any)String
matcher(1) //>r1: String = one
matcher(2) //>r2: String = Other integer
matcher(persons) //>r3: String = List with Person(Or,Doe)
matcher(List(1,2)) //> r4: String = List with 1
matcher(Person( "John","Doe"))//> r5: String = Hello, John!
matcher("Alma") //> r6: String = Nothing else matched
===========================================================
final case class ::[B](override val head: B, private[scala]
var tl: List[B]) extends List[B] {
override def tail : List[B] = tl
override def isEmpty: Boolean = false
}
Mi is az a Scala? - magassabb rendű fgvények
● Objektum-orientált funkcionális
programozási nyelv
– a függvények egyszerű
objektumok
– unified types
– pattern matching
– magassabb rendű
függvények
def sum(f: Int => Int, a: Int, b: Int): Int =
if (a > b) 0 else f(a) + sum(f, a + 1, b)
===========================================================
def sumInts(a: Int, b: Int): Int = sum(id, a, b)
def sumSquares(a: Int, b: Int): Int = sum(square, a, b)
def sumPowersOfTwo(a: Int, b: Int): Int =
sum(powerOfTwo, a, b)
def id(x: Int): Int = x
def square(x: Int): Int = x * x
def powerOfTwo(x: Int): Int =
if (x == 0) 1 else 2 * powerOfTwo(x - 1)
==========================================================
def sumInts(a: Int, b: Int): Int = sum(x => x, a, b)
def sumSquares(a: Int, b: Int): Int = sum(x => x * x, a, b)
Mi is az a Scala? - Currying
● Objektum-orientált funkcionális
programozási nyelv
– a függvények egyszerű
objektumok
– unified types
– pattern matching
– magassabb rendű
függvények
– részleges függvény
alkalmazás (currying)
def sum(f: Int => Int)(a: Int, b: Int): Int =
if (a > b) 0 else f(a) + sum(f)(a + 1, b)
===========================================================
val sumInts = sum(x => x)
val sumSquares = sum(x => x * x)
val sumPowersOfTwo = sum(powerOfTwo)
// (a:Int,b:Int)=>Int
===========================================================
sumInts(1,10)
sumSquares(1, 10)
sumPowersOfTwo(10, 20)
Mi is az a Scala? - Immutable adatszerkezetek
● Objektum-orientált funkcionális
programozási nyelv
– a függvények egyszerű
objektumok
– unified types
– pattern matching
– magassabb rendű
függvények
– részleges függvény
alkalmazás (currying)
– hatékony immutable
adatszerkezetek
Miért pont a Scala?
● Skálázódó megoldásokat kerestünk
– kiválasztott keretrendszereket Scalaban fejlesztették (akka, Play Framework)
● A nyelv funkcionális természete könnyebbé teszi a többszálú alkalmazások írását
– kevesebb mutable állapot
– Future-ök és az Actor modell
● Kockázatcsökkentő tényezők
– Sikeres POC
– Könnyed együttműködés a Javával
● Java libraryk használhatóak
● A java osztályok a Scala típusrendszer részét képezik
● Egy projekten belül és keverhetjük az implementációs nyelvet
● Fejlesztőként miért?
– Érdekes
– Kevesebb boilerplate kód
Kezdeti nehézségek
● Nyelvi különbségek
● Funkcionális megközelítés
– side effect mentes kód
● Rengeteg lehetőség
– kiválasztani a “megoldásokat”
– kialakítani egy egységes coding standardet
Pro és Kontra ( Java 8 vs. Scala)
Scala:
case class Person(firstName:String,
lastName:String)
Java:
public class Person
{
private String firstName;
private String lastName;
String getFirstName () { return firstName; }
void setFirstName (String firstName) {
this.firstName = firstName;}
String getLastName () { return lastName;}
void setLastName (String lastName) {
this.lastName = lastName;
}
int hashCode() ....
boolean equals(Object o) { .... }
}
Pro és Kontra ( Java 8 vs. Scala)
Scala:
list.sortWith((x,y) => {
val cmp=x.lastName.compareTo(y.lastName)
if (cmp==0)
x.firstName.compareTo(y.firstName)< 0
else cmp<0
})
Java:
list.sort((x,y)-> {
int cmp=x.lastName.compareTo(y.lastName);
return cmp!=0 ? cmp :
x.firstName.compareTo(y.firstName)
}
Lambda kifejezések
Pro és Kontra ( Java 8 vs. Scala)
Scala:
import scala.math._
var (maxFirstLen, maxSecondLen) = (0, 0)
list.foreach { x =>
maxFirstLen =
max(maxFirstLen, x.firstName.length)
maxSecondLen =
max(maxSecondLen, x.lastName.length)
}
Java:
Lambda kifejezések
Pro és Kontra ( Java 8 vs. Scala)
Scala:
trait AsyncInput[T]{
def onReceive(acceptor: T=>Unit): Unit
def read: Future[T] = {
val p = Promise[T]()
onReceive(p.success(_))
p.future
}
}
==================================================
Java:
interface AsyncInput<T> {
void onReceive(Acceptor<T> acceptor);
default Future<T> read() {
final CompletableFuture<T> promise=
new CompletableFuture<>();
onReceive(x -> promise.complete(x));
return promise;
}
}
===================================================
Interfész alapértelmezett metódussal
Pro és Kontra ( Java 8 vs. Scala)
Scala:
trait LoggedAsyncInput[T] extends AsyncInput[T]{
abstract override def onReceive(
acceptor: T => Unit) : Unit = {
super.onReceive(x => {
println(s "received:${x}")
acceptor(x)
})
}
}
=================================================
trait MyToString {
override def toString = s "[${super.toString}]"
}
Java:
Interfész alapértelmezett metódussal
Pro és Kontra ( Java 8 vs. Scala)
Scala:
persons.filter(_.firstName == "Jon")
=============================================
persons.par.filter(_.firstName == "Jon")
Java:
persons.stream().filter( x ->
x.firstName.equals( "Jon"))
.collect(Collectors.toList())
==========================================
persons.parallelStream().filter( x ->
x.firstName== "Jon")
.collect(Collectors.toList())
Stream műveletek a Collectionökön
Scala sajátosságok
● Miért érdemes a scalát választani?
– A nyelv struktúráltsága
● DSL
– típusos
– használható a nyelvi struktúrákban
● Mi teszi ezt lehetővé?
– Flexibilis szintaxis, a különböző szintaktikus cukorkák
– Paraméterek név szerinti átadása és annak szintaxisa
– Makrók
Scala sajátosságok - Flexibilis szintaxis I.
● Metódusoknak tetszőleges neve lehet
○ def +++(x:Int, y:Int) = x*x*y*y
● Az egy paraméterrel rendelkező metódusok meghívhatóak infix módon
○ 1 to 100 == 1.to(100)
● A kerek és a kapcsos zárójel felcserélhetősége
○ future(1) == future{1}
● Egy függvényt definiálhatunk több paraméterlistával is
○ def until(cond: =>Boolean)(body: => Unit) : Unit
● ...
Scala sajátosságok - Flexibilis szintaxis II.
● Kód blokkokat is átadhatunk
függvény paraméterként név
szerinti átadással
○ Példa DSL
object Do {
def apply(body: => Unit) = new DoBody(body)
}
class DoBody(body: => Unit) {
def until(cond: => Boolean): Unit ={
body
while (cond) body
}
}
================================================
var x = 0
Do {
x = x + 1
} until (x < 10)
Ami kimarad az előadásból
● Makrók
○ http://docs.scala-lang.org/overviews/macros/usecases.html
● For comprehension
○ Ezek használata a saját adatszerkezeteken
■ foreach
■ flatMap
■ map
● Monádok
● Monoidok
● Unchecked Exceptions