Przygotował: Jacek Sroka. JNP 3 język Scala

Podobne dokumenty
Przygotował: Jacek Sroka. Scala Wprowadzenie

Samouczek Scali dla programistów Javy

Programowanie obiektowe

Scala. Obiektowo-funkcyjny język programowania. Zbyszek Skowron

Klasy abstrakcyjne, interfejsy i polimorfizm

Platformy Programistyczne Podstawy języka Java

Język programowania Scala / Grzegorz Balcerek. Wyd. 2. Poznań, cop Spis treści

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

PARADYGMATY PROGRAMOWANIA Wykład 4

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Programowanie w Internecie. Java

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Wstęp do ruby dla programistów javy

Programowanie obiektowe

Przygotował: Jacek Sroka. PO* - Scala (iteratory, leniwość, view bounds i konwersje)

Dokumentacja do API Javy.

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Wykład 7: Pakiety i Interfejsy

KOTLIN. Język programowania dla Androida

Kurs WWW. Paweł Rajba.

JavaScript funkcyjność

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Język programowania Scala + aktorzy Akka

Języki Programowania II Wykład 3. Java podstawy. Przypomnienie

Programowanie obiektowe

Co jeszcze mogą nam dać adnotacje? Adam Warski

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Programowanie obiektowe

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie w Javie - wykład 3

Polimorfizm. dr Jarosław Skaruz

Programowanie obiektowe

Programowanie obiektowe

Dziedziczenie. dr Jarosław Skaruz

WYKORZYSTANIE JĘZYKA GROOVY W TESTACH JEDNOSTKOWYCH, INTEGRACYJNYCH I AUTOMATYCZNYCH. Mirosław Gołda, Programista Java

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Programowanie Komputerów

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

DIAGRAMY SYNTAKTYCZNE JĘZYKA TURBO PASCAL 6.0

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Programowanie obiektowe

Podstawowe części projektu w Javie

Programowanie obiektowe

Programowanie RAD Delphi

Tworzenie aplikacji w języku Java

Wstęp do programowania. Różne różności

Klasy abstrakcyjne i interfejsy

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

Wykład 4: Klasy i Metody

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Java Język programowania

Podstawy programowania skrót z wykładów:

Współbieżność w środowisku Java

20. Pascal i łączenie podprogramów Pascala z programem napisanym w C

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

1 Atrybuty i metody klasowe

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Dawid Gierszewski Adam Hanasko

Dziedziczenie. Tomasz Borzyszkowski

Wstęp do programowania

Wstęp do Programowania 2

Programowanie Obiektowe i C++

dziedziczenie - po nazwie klasy wystąpią słowa: extends nazwa_superklasy

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1)

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Programowanie w Javie - wykład 2

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Polimorfizm a klasy generyczne w języku Java. Zdzisław Spławski 1

Wprowadzenie do języka Java

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Java podstawy jęyka. Wykład 2. Klasy abstrakcyjne, Interfejsy, Klasy wewnętrzne, Anonimowe klasy wewnętrzne.

Programowanie w środowiskach graficznych. Wykład 3 Język C#

Kurs programowania. Wykład 9. Wojciech Macyna

dr inż. Piotr Czapiewski Tworzenie aplikacji w języku Java Laboratorium 1

Podejście obiektowe. Tablice obiektów Przykład 1 metody i atrybuty statyczne oraz niestatyczne

Wykład 6: Dziedziczenie

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

JAVA- wykład 2 Klasy

Szablony klas, zastosowanie szablonów w programach

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Scala. Wprowadzenie do języka.


Laboratorium Wstawianie skryptu na stroną: 2. Komentarze: 3. Deklaracja zmiennych

Definicje klas i obiektów. Tomasz Borzyszkowski

4. Funkcje. Przykłady

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 6

Programowanie obiektowe zastosowanie języka Java SE

Języki i metody programowania Java INF302W Wykład 2 (część 1)

Programowanie komputerowe. Zajęcia 7

Transkrypt:

1 JNP 3 język Scala

2 Czemu Scala? Język wzorowany na Javie i Haskelu nowoczesny obiektowy język programowania jednocześnie język funkcyjny Programy uruchamiają się na JVM można swobodnie odwoływać się do istniejącego kodu i bibliotek Javy Silnie typowany ciekawy system typów Zwięzła składnia i silniejsza abstrakcja = prostsze programy = mniej błędów Zaprojektowany do wyrażania powszechnych wzorców projektowych Robi się trendy?

3 Pierwszy przykład object HelloWorld { def main(args: Array[String]) { println("hello, world!") > scalac HelloWorld.scala > scala -classpath. HelloWorld Hello, world! main() jest procedurą object deklaruje Singleton (klasa i egzemplarz) Nie ma potrzeby dla składowych statycznych

4 Jak uruchamiać - shell > scala This is a Scala shell. Type in expressions to have them evaluated. Type :help for more information. scala> object HelloWorld { def main(args: Array[String]) { println("hello, world!") defined module HelloWorld scala> HelloWorld.main(null) Hello, world! scala>:q

5 Jak uruchamiać - skrypt #!/bin/sh exec scala "$0" "$@"!# object HelloWorld { def main(args: Array[String]) { println("hello, world! " + args.tolist) HelloWorld.main(args) >./script.sh

6 Jak uruchamiać - kompilacja Kompilacja do bytecodu Javy > scalac HelloWorld.scala lub > scalac -d classes HelloWorld.scala Uruchamianie > scala HelloWorld lub > scala -classpath classes HelloWorld argumentem powinien być obiekt najwyższego poziomu jeżeli występuje klauzula extends Application to wykonywane są wszystkie polecenia object HelloWorld2 extends Application { println("hello, world!") wpp wykonywana jest metoda main

7 Wygodniejsze importy import java.util.{date, Locale import java.text.dateformat import java.text.dateformat._ Zwięzłe importowanie wielu klas z pakietu _ zamiast * object FrenchDate { def main(args: Array[String]) { val now = new Date val df = getdateinstance(long,locale.france) println(df format now) Trochę inne niż w javie importowanie składowych statycznych Funkcyjna składnia wywoływania metod i przekazywania parametrów Domyślnie importowane jest całe java.lang

8 Wszystko jest obiektem Włącznie z liczbami i funkcjami. 1 + 2 * 3 / x (1).+(((2).*(3))./(x)) 1.+(2) (1).+(2) //żeby lexer nie wybrał najdłuższego dopasowanie dla identyfikatorów

Funkcje też są obiektami object Timer { def oncepersecond(callback: () => Unit) { while (true) { callback(); Thread sleep 1000 def timeflies() { println("time flies like an arrow...") def main(args: Array[String]) { oncepersecond(timeflies) object TimerAnonymous { def oncepersecond(callback: () => Unit) { while (true) { callback(); Thread sleep 1000 Możemy przekazywać funkcje jako parametry () => Unit to typ wszystkich funkcji bez argumentów i bez wartości zwrotnej Do wypisywanie użyliśmy predefiniowanej metody println() zamiast System.out Często wygodnie jest używać funkcji anonimowych def main(args: Array[String]) { OncePerSecond(() => println("time flies like an arrow...")) 9

10 Klasy class Complex(real: Double, imag: Double) { def re() = real def im() = imag object ComplexNumbers { def main(args: Array[String]) { val c = new Complex(1.2, 3.4) println("imaginary part: " + c.im()) class Complex(real: Double, imag: Double) { def re = real def im = imag Klasy w Scali mają parametry new Complex(1.5, 2.3) Typy zwrotne metod zazwyczaj mogą być wywnioskowane przez kompilator Wywołując metody z zerową liczbą argumentów trzeba wstawiać puste nawiasy Metody można zdefiniować jako bezparametrowe Domyślną nadklasą jest scala.anyref class Complex(real: Double, imag: Double) { Przedefiniowując metody trzeba to def re = real jawnie wskazać def im = imag override def tostring() = "" + re + (if (im < 0) "" else "+") + im + "i"

11 Warianty i dopasowywanie abstract class Tree case class Sum(l: Tree, r: Tree) extends Tree case class Var(n: String) extends Tree case class Const(v: Int) extends Tree //taką funkcją możemy //reprezentować środowisko //dla "x" zwraca 5 wpp wyjątek { case "x" => 5 //alias dla typu type Environment = String => Int Wsparcie do reprezentacji drzew, np. XML Przykład: kalkulator z sumowaniem, stałymi całkowitymi i zmiennymi Const(5) zamiast new Const(5) Automatycznie są gettery np. dla c egzemplarza Const mamy c.v equals i hashcode działają na strukturze tostring wypisuje "literał np. Sum(Var(x,Const(1))) Można dopasowywać do wzorca

12 Warianty i dopasowywanie c.d. def eval(t: Tree, env: Environment): Int = t match { case Sum(l, r) => eval(l, env) + eval(r, env) case Var(n) => env(n) case Const(v) => v //jak nic się nie dopasuje to wyjątek def derive(t: Tree, v: String): Tree = t match { case Sum(l, r) => Sum(derive(l, v), derive(r, v)) case Var(n) if (v == n) => Const(1) //dopasowanie warunkowe case _ => Const(0) //guard def main(args: Array[String]) { val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y"))) val env: Environment = { case "x" => 5 case "y" => 7 println("expression: " + exp) //Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y))) println("evaluation with =5, y=7: " + eval(exp, env)) //Evaluation with x=5, y=7: 24 println("derivative relative to x: " + derive(exp, "x")) //...to x: Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0))) println("derivative relative to y: " + derive(exp, "y")) //..to y: Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))

13 Dopasowywanie wzorców vs polimorfizm Przy pomocy dopasowywania wzorców bardzo łatwo dodać nową metodę dla całej hierarchii. Dużo roboty jak nowy węzeł. Za pomocą polimorfizmu łatwo dodać nowy rodzaj węzła. Dużo roboty jak nowa metoda.

14 Traits trait Ord { def < (that: Any): Boolean def <=(that: Any): Boolean = (this < that) (this == that) def > (that: Any): Boolean =!(this <= that) def >=(that: Any): Boolean =!(this < that) Wzbogacanie klasy (interfejs z implementacją) Any to bardziej ogólny Object

15 Traits c.d. class Date(y: Int, m: Int, d: Int) extends Ord { def year = y; def month = m def day = d override def tostring(): String = year + "" + month + "" + day override def equals(that: Any): Boolean = that.isinstanceof[date] && { val o = that.asinstanceof[date] o.day == day && o.month == month && o.year == year def <(that: Any): Boolean = { if (!that.isinstanceof[date]) error("cannot compare " + that + " and a Date") val o = that.asinstanceof[date] (year < o.year) (year == o.year && (month < o.month (month == o.month && day < o.day)))

16 Generyki class Reference[T] { private var contents: T = _ def set(value: T) { contents = value def get: T = contents Parametryzowanie kodu typami Piszemy ogólny kod i nie musimy bez przerwy rzutować "_ to wartość domyślna dla zmiennej object IntegerReference { def main(args: Array[String]) { val cell = new [Int] cell.set(13) println("reference contains the half of " + (cell.get * 2))

17 Quicksort def sort(a: Array[Int]) { def swap(i: Int, j: Int) { val t = a(i); a(i) = a(j); a(j) = t def sort1(l: Int, r: Int) { val pivot = a((l + r) / 2) var i = l var j = r while (i <= j) { while (a(i) < pivot) i += 1 while (a(j) > pivot) j -= 1 if (i <= j) { swap(i, j) i += 1 j -= 1 if (l < j) sort1(l, j) if (j < r) sort1(i, r) deklaracje zaczynają się zarezerwowanym słowem: def, var, val typ podajemy po symbolu i : jak się da to kompilator domyśli się typu i nie trzeba go podawać Array[Int] zamiast Int[] a(i) zamiast a[i] zagnieżdżone funkcje mają dostęp do parametrów i zmiennych if (a.length > 0) sort1(0, a.length - 1)

18 Quicksort c.d. object sort { def sort(a: Array[Int]) { //... def println(ar: Array[Int]) { def print1 = { def iter(i: Int): String = ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") if (ar.length == 0) "" else iter(0) Console.println("[" + print1 + "]") def main(args: Array[String]) { val ar = Array(6, 2, 8, 5, 1) println(ar) sort(ar) println(ar)

19 Quicksort wersja funkcyjna def sort(a: Array[Int]): Array[Int] = { if (a.length < 2) a else { val pivot = a(a.length / 2) Array.concat(sort(a.filter(x => x < pivot)), a.filter(x => x == pivot), sort(a.filter(x => x > pivot))) Obiekty Array[T] mają metodę (pochodzącą z klasy Seq[T]) def filter(p: T -> Boolean): Array[T] Można użyć składni a.filter(_ < pivot) a nawet (partially applied function) a.filter(pivot >) Operatory przekładają się na wywołania metod: a filter (pivot >) Dla podstawowych operatorów kompilator powinien generować dobry kod Ponieważ ciało funkcji jest wyrażeniem można pominąć {

20 Dyskusja zapotrzebowanie na pamięć wielowątkowość

21 Funkcje wyższego rzędu def While (p: => Boolean) (s: => Unit) { if (p) {s; While(p)(s) tak naprawdę jest specjalna konstrukcja oba parametry są bezparametrowe Unit to tak jakby void jak nie zwracamy żadnego wyniku to tak jak byśmy zwracali () nie trzeba podawać return, domyślnie wynikiem funkcji jest wynik ostatniego wyrażenia

22 Wyrażenia scala> 87+145 res0: Int = 232 scala> 5+2*3 res1: Int = 11 scala> "hello"+" world!" res2: java.lang.string = hello world! scala> def pi = 3.141592 pi: Double scala> def radius = 10 radius: Int scala> 2*pi*radius res7: Double = 62.83184

23 Kiedy jest wyliczana wartość? wyrażenie w def x = e jest wyliczane dopiero jak jest potrzebne wyrażenie w val x = e jest wyliczane w chwili deklaracji zazwyczaj wyrażenia wyliczane są od lewej (redukcja) (2*pi)*radius (2*3.141592)*radius 6.183184*radius 6.183184*10 61.83184

24 Proste funkcje scala> def square(x: Double) = x*x square: (Double)Double scala> square(2) res11: Double = 4.0 scala> square(5+3) res12: Double = 64.0 scala> square(square(4)) res13: Double = 256.0 scala> def sumofsquares(x: Double, y: Double) = square(x)+square(y) sumofsquares: (Double,Double)Double scala> sumofsquares(3,2+2) res14: Double = 25.0

Wyliczanie wartość funkcji call-by-value sumofsquares(3, 2+2) sumofsquares(3, 4) square(3)+square(4) 3*3+square(4) 9+square(4) 9+4*4 9+16 25 call-by-name sumofsquares(3, 2+2) square(3)+square(2+2) 3*3+square(2+2) 9+square(2+2) 9+(2+2)*(2+2) 9+4*4 9+16 25 Dla czystych funkcji zawsze ten sam wynik call-by-value nie powtarza wyliczania argumentów Zazwyczaj bardziej wydajny call-by-name nie wylicza nieużywanych (niepotrzebnych) argumentów 25

26 Wyliczanie wartości funkcji c.d. call-by-value łatwiej zapętlić scala> def loop: Int = loop loop: Int scala> def first(x: Int, y: Int) = x first: (Int,Int)Int scala> first(1,loop) call-by-name można wymusić scala> def constone(x:int, y: => Int) = 1 constone: (Int,=> Int)Int scala> constone(1,loop) res2: Int = 1 scala> constone(loop,1)//pętla

27 If-else Jak w Javie, ale w Scali jest również wyrażeniem (jak Javowy operator ternarny...?... :...) scala> def abs(x: Double) = if (x >= 0) x else -x abs: (Double)Double Stałe logiczne i operatory są takie same jak w Javie

28 Metoda Newtona y x/y (y+x/y)/2 1 2/1 = 2 1.5 1.5 2/1.5 = 1.3333 1.4167 1.4167 2/1.4167 = 1.4118 1.4142 1.4142......

29 Przykład rozwiązania def sqrt(x: Double) = sqrtiter(1.0, x) def sqrtiter(guess: Double, x: Double): Double = if (isgoodenough(guess, x)) guess else sqrtiter(improve(guess, x), x) def improve(guess: Double, x: Double) = (guess + x/guesss)/2 def isgoodenough(guess: Double, x: Double) = abs(square(guess) x) < 0.001

Zagnieżdżanie funkcji pomocniczych def sqrt(x: Double) = { def sqrtiter(guess: Double, x: Double): Double = if (isgoodenough(guess, x)) guess else sqrtiter(improve(guess, x), x) def improve(guess: Double, x: Double) = (guess + x/guesss)/2 def isgoodenough(guess: Double, x: Double) = abs(square(guess) x) < 0.001 sqrtiter(1.0, x) //bloki w Scali są wyrażeniami o wartości kończącego wyrażenia 30

31 Standardowa widoczność w zagnieżdżonych blokach def sqrt(x: Double) = { def sqrtiter(guess: Double): Double = if (isgoodenough(guess, x)) guess else sqrtiter(improve(guess, x), x) def improve(guess: Double) = (guess + x/guesss)/2 def isgoodenough(guess: Double) = abs(square(guess) x) < 0.001 sqrtiter(1.0)

32 ; każda definicja w bloku musi się kończyć ; domyślny średnik jest dodawany na końcu każdej linii, chyba że: linia kończy się słowem lub operatorem infiksowym, które nie byłyby dozwolone na końcu wyrażenia następna linia zaczyna się słowem od którego nie mogłoby się zaczynać wyrażenie jesteśmy otoczeni nawiasami def f(x: Int) = x + 1; f(1)+f(2) def g(x: Int) = x + 1 g(1)+g(2) def h(x: Int) = {x+1; h(1)+h(2) //tu średnik jest obowiązkowy

33 ; def m(x: Int) = x + y m(1)*m(2) def n(x: Int) = ( x //nawiasy powodują brak średnika + y ) n(1)/n(2)

34 Rekursja ogonowa def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) gcd(14, 21) if (21 == 0) 14 else gcd(21, 14 % 21) if (false) 14 else gcd(21, 14 % 21) gcd(21, 14 % 21) gcd(21, 14) if (14 == 0) 21 else gcd(14, 21 % 14) gcd(14, 21 % 14) gcd(14, 7) if (7 == 0) 14 else gcd(7, 14 % 7) gcd(7, 14 % 7) gcd(7, 0) if (0 == 0) 7 else gcd(0, 7 % 0) 7

35 Rekursja ogonowa def factorial(n: Int): Int = if (n == 0) 1 else n * factorial(n-1) factorial(5) if (5 == 0) 1 else 5 * factorial(5 1) 5 * factorial(5 1) 5 * factorial(4) 5 * (4 * factorial(3)) 5 * (4 * (3 * factorial(2))) 5 * (4 * (3 * (2 * factorial(1)))) 5 * (4 * (3 * (2 * (1 * factorial(0)))) 5 * (4 * (3 * (2 * (1 * 1)))) 120