Principles of programming in scala

24
SCALA ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ Jakub Kohout, leden 2014 Hradec Králové 1

Transcript of Principles of programming in scala

Page 1: Principles of programming in scala

SCALAZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Jakub Kohout, leden 2014

Hradec Králové

1

Page 2: Principles of programming in scala

• Základy jazyka• Syntaxe• Základní konstrukty• Kolekce• Podpora distribuovaných aplikací a konkurenčního

programování

2

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 3: Principles of programming in scala

• Zásady objektového paradigmatu programování– Abstrakce– Zapouzdření– Dědičnost– Polymorfismus– SOLID design principles*

• Single responsibility principle• Open closed principle• Liskov substitution principle• Interface segregation principle• Dependency injection

– Favor composition over inheritance– DRY (don‘t repeat yourself)

*http://javarevisited.blogspot.cz/2012/03/10-object-oriented-design-principles.html

3

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 4: Principles of programming in scala

• Zásady funkcionálního paradigmatu programování– no method side effects

• metody by měly vždy vracet stejný výpočet při stejných vstupních datech --> opačné oproti imperativnímu styly programování

– immutable variables• neměnné proměnné (list, set, map)

– Rekurze (tail recursion, accumulator), labda kalkulus „=>“– metody jsou méně spletité, jsou více znovupoužitelné a spolehlivé– metody by měly komunikovat s prostředím pouze skrze vstupní

argumenty a návratové hodnoty

4

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 5: Principles of programming in scala

• scalable language• určený pro psaní malých skriptů i rozsáhlých systémů, • běží na standardní JVM, i nestandartní JVM (Dalvik)• Scala kód je kompilován do bytekódu

– kompilátor pro Scalu vytvořen tvůrcem kompilátoru Javy• dokáže využívat všechny existující Java knihovny, podpora .NET• v případě absence IDE, je možné použít kompilátor SBT s interpretem příkazů

REPL• propaguje kombinaci objektově orientovaného a funkcionálního konceptu

programování • díky konstruktům funkcionálního jazyka umožňuje psát snadno a velmi rychle

jednoduché algoritmy• díky konstruktům OO jazyka umožňuje snadno vytvářet rozsáhlé systémy• scala je čistě objektový orientovaný jazyk, ne jako Java*• vše je objekt - i volání anonymní funkce

* Scala neumožňuje vytvařet statické proměnné a metody, nemá primitivní typy5

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 6: Principles of programming in scala

• výkonnost kódu většinou stejná jako Java• scala využívá hodně knihoven Javy, obohacuje je

– konverze mezi datovými typy, práce s kolekcemi– využívá i primitivní typy Javy (o jejich použití rozhoduje kompilátor)

• Scala is not just a nicer Java.• je to bohatší jazyk, odstraňuje nadbytečný kód - o polovinu kratší programy

Java zápisclass MyClass { private int index; private String name;

public MyClass(int index, String name) { this.index = index; this.name = name; }}

Scala zápisclass MyClass(index: Int, name: String){ }

6

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 7: Principles of programming in scala

• Prvky programovacího jazyka Scala– syntaxe z Java, C# *– exekuční model, class knihovny, základní datové typy z Javy– uniform object model ze Smalltalku (pak Ruby)– přístup k funkcionálnímu programování je z SML, OCaml, F#– funkce vyššího řádu - Haskel, ML– actor concurency library - Erlang– další Lisp, C++, Iswim, Algol, Simula, Beta

• úplné novinky– traits - umožňuje snadnou kompozici objektů– abstract types - více OO alternativa ke generickým typům– pattern matching

• Jazyky které kombinují funkcionální a objektový přístup k progamování • Ruby, Python, Smalltalk

*syntaxe Java a C# převzata z C, C++

7

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 8: Principles of programming in scala

• staticky typovaný jazyk

• výhody – odstraňuje hodně kompilačních chyb (například zabrání pokusu nastavit

do Int proměnné třeba Boolean hodnotu)– lepší dokumentace kódu– pohodlnější refaktoring - opravíte jednu část kódu a okamžitě vidíte,

které další části byly opravou zasaženy

• nevýhody– běžně bývají více "ukecané"

8

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 9: Principles of programming in scala

• Proměnné– val - values (neměnné)– var - variables (proměnné) – typ není nutné většinou deklarovat explicitně (odvozen)– hodnota proměnné je vyhodnocena okamžitě– lazy val - hodnota proměnné je vyhodnocena až při prvním použití– obsahuje pouze referenční datové typy, i když kompilátor následně

používá Java primitivní typy, tam kde je to možné kvůli výkonnosti

• N-tice (Tuples)– n-tice hodnot libovolných datových typů

val pair = ("value" , 1022 )

val (label, number) = pair pair._1 pair._2

pair.swap

9

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 10: Principles of programming in scala

• Metody – s návratovým typem (nemusí být většinou explicitně uveden)

def func(x: Int, y: Int):Int = x + y

•funkce je vyhodnocena při zavolání•návratový typ je nutné uvést pokud je funkce volána rekurzivně

– bez návratového typudef func(x: Int, y: Int) {}

•kód je vyhodnocen při každém volání– anonymní funkce, uložená do proměnné

val f = (x: Int) => x + 1

•kod je vyhodnocen pouze jednouf(4) > res4: Int = 5

– částečné volání metodydef func(x: Int, y: Int, z: Int): Int = x + y + zval f = func(2, _: Int, _: Int) *f(3, 4) > res6: Int = 9

*vytvoří funkci! tj. Objekt pomocí metody apply, apply volá func pouze jednou10

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 11: Principles of programming in scala

• Metody – Funkce vyššího řádu (higher order functions)

• jsou to metody, které přebírají nějakou funkci jako parametr, nebo vrací funkci jako návratový typ

def suma(f: Int => Int): (Int, Int) => Int = { def sumf(a: Int, b: Int): Int = if (a < b) f(a) + sumf(a + 1, b) else f(b) sumf}

11

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 12: Principles of programming in scala

• Metody – Currying

• rozdělení více vstupních parametrů do skupin za účelem postupného provedení funkce

• konstrukt patří do takzvaných control abstractionsdef suma(f: Int => Int)(a: Int, b: Int): Int = { if (a < b) f(a) + suma(f)(a + 1, b) else f(b)}val partialResult = suma(x => x * x * x)_val result = partialResult(1, 10)

• jiný zápis a volání fcedef suma(a: Int, b: Int)(f: Int => Int): Int = { if (a < b) f(a) + suma(a + 1, b)(f) else f(b)} suma(1,10) { x => x * x * x}

12

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 13: Principles of programming in scala

• Metody – Proměnná délka argumentů metody

 def transform(f: Int => Int)(numbers: Int*) = {   numbers.map(number => f(number)) }

 transform(x => x*x)(1, 2, 3, 4, 5)  

– volání funkce, která nemá parametry - může být bez závorek --> function– parametry metod jsou defaultně val– return nemusí být explicitně v metodách uvedeno, Scala vrací výsledek

posledního výpočtu metody– je vhodné psát metody bez klíčového slova return, podporuje to funkční

dekompozici a vytváření malých(přehlednějších) funkcí

13

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 14: Principles of programming in scala

• Třídy– stejně jako v Javě– proměnná bez modifikátoru je defaultně public (private, protected musí

být uvedeno explicitně)class MyClass(c: String) {       val color = c              def printColor() {              println(color)       }  }  val cla = new MyClass("cerna" )                    cla.color                                        cla.printColor

– nemají statické proměnné a metody•statické proměnné v Javě* jsou v rozporu se zásadami OOP - narušuje zapouzdření

*statické proměnné jsou používány jako náhražka scoped proměnných(session), problémem je, že mohou být změněny, například, když v dané JVM běží dvě instance programu, který má stejné statické proměnné (tyto proměnné jsou v JVM pouze jednou, sdíleny oběma programy)14

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 15: Principles of programming in scala

• Trait– Kolekce polí a chování, které mohou rozšiřovat nějakou třídu– třída může být rozšiřována jedním, nebo více traity– pro rozšíření třídy o trait se používá klíčové slovo with– Jedním ze zásad SOLID (interface segregation principle) je následující:

• když třída implementuje interface, měla by implementovat všechny jeho metody

• stává se, že v aplikaci existuje několik implementací jednoho interface, ale ne každá třída potřebuje implementovat všechny metody trait Car {   val brand: String } trait Shiny {   val shineRefraction: Int } class BMW extends Car with Shiny {   val brand = "BMW"   val shineRefraction = 12 }

15

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 16: Principles of programming in scala

• Objekty– objekt představuje singleton– využívány jako Factory se statickými metodami– objekt se může jmenovat stejně jako třída, pokud je takový definován ve

stejném zdrojovém souboru jako daná třída, pak se nazývá class companion object

– třída a její companion objekt mohou sdílet své privátní proměnné– nemohou přebírat parametry v konstruktoru, protože nemohou být

instanciovány– jsou inicializovány při prvním přístupu k nim

16

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 17: Principles of programming in scala

• Pattern matching– používáno pro dekompozici datových struktur– nahrazuje např. použití instanceOf nebo switch - case , nebo if-

else statementuval value = "1"                                 val result = value match {    case "1" => "one"    case "2" => "two"    case _ => "nothing"  }

– Pattern match lze provádět i na úrovni tříd• je potřeba definovat takzvané case classes

abstract class Exprcase class Var(name: String) extends Exprcase class Number(num: Double) extends Exprcase class UnOp(operator: String, arg: Expr ) extends Expr

17

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 18: Principles of programming in scala

• for– nejedná se o klasický cyklus, ale o kombinaci jiný konstruktů– může být plně nahrazen kontrukty: map, flatMap, filter– klasický:

for(i <- 1 to 10) {  println(i)}

– dvojí iterace:for{i <- 1 to 10    j <- 1 to 10}yield (i,j)

18

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 19: Principles of programming in scala

• Kolekce (immutable)– List – Stream 

• Podobné jako list, vždy je vyhodnocena jen hlava, tělo je vyhodnoceno až na požádání

– Vector – Range 

• Seřazená rovnoměrně rozdělená sekvence čísel– String 

• Jako v Javě, implicitně je konvertován na Seq[Char]– Map – Set 

• Bez duplicit

19

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 20: Principles of programming in scala

• Kolekce (immutable)– xs exists p // true if there is at least one element for which predicate p is true– xs forall p // true if p(x) is true for all elements – xs zip ys // returns a list of pairs which groups elements with same index

together – xs unzip // opposite of zip: returns a pair of two lists – xs.flatMap f // applies the function to all elements and concatenates the

result – xs.sum // sum of elements of the numeric collection – xs.product // product of elements of the numeric collection– xs.max // maximum of collection – xs.min // minimum of collection – xs.flatten // flattens a collection of collection into a single-level collection – xs groupBy f // returns a map which points to a list of elements– xs distinct // sequence of distinct entries (removes duplicates)

20

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 21: Principles of programming in scala

• Podpora reaktivního programování– Rx library– Try[T] – ošetření chyb– Future[T] – asynchronní zpracování, ošetření chyb– Observable[T] – asynchronní zpracování streamu– Scheduler – provedení bloku kódu v nové vlákně

• Aktéři– akka library– Pro vývoj systémů postavených na základě lidské interakce– Aktéři jsou nezávislé entity, které si mezi sebou zasílají zprávy

21

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 22: Principles of programming in scala

• Aktéři

object BankAccount { case class Deposit(amount: BigInt) { require(amount > 0) } case class Withdraw(amount: BigInt) { require(amount > 0) } case object Done case object Failed }

class BankAccount extends Actor { import BankAccount._ var valance = BigInt(0) def receive = { case Deposit(amount) => balance += amount sender ! Done case Withdraw(amount) if amount <= balance => balance -= amount sender ! Done case _ => sender ! Failed }

}

22

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 23: Principles of programming in scala

• Shrnutí– Výhody

• Jazyk umožňující jak funkcionální tak objektový styl programování• Rošiřitelný• Bohatší jazyk, více konstruktů• Podpora asynchronního zpracování• Podpora distribuovaného zpracování – akka • Kód je kratší a přehlednější• Výkonnost přibližně stejná jako Java

– Nevýhody• Blížící se Java 8 ?

23

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ

Page 24: Principles of programming in scala

• Zdroje– http://twitter.github.io/scala_school/– http://docs.scala-lang.org/tutorials/tour/tour-of-scala.html– http://www.tutorialspoint.com/scala/

• Online kurzy– https://www.coursera.org/course/progfun– https://www.coursera.org/course/reactive

24

SCALA - ZÁKLADY FUNKCIONÁLNÍHO PROGRAMOVÁNÍ