Scala + NetBeans AKA: Nowoczesne obiektowe języki programowania i środowiska programistyczne na przykładzie Scali i środowiska NetBeans

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

Programowanie obiektowe

Przygotował: Jacek Sroka. PO* - Scala (typy uogólnione, listy)

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

Programowanie obiektowe

KOTLIN. Język programowania dla Androida

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

Platformy Programistyczne Podstawy języka Java

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

Programowanie obiektowe

Programowanie i projektowanie obiektowe

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne

PO* - Scala (typy uogólnione, listy)

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

Wstęp do programowania

Scala. Wprowadzenie do języka.

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

Klasy abstrakcyjne, interfejsy i polimorfizm

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

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

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Podstawy Programowania C++

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

Wprowadzenie do języka Java

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

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

JAVA. Platforma JSE: Środowiska programistyczne dla języka Java. Wstęp do programowania w języku obiektowym. Opracował: Andrzej Nowak

Języki skryptowe w programie Plans

Podstawowe części projektu w Javie

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

Wykład 4: Klasy i Metody

Tworzenie stron internetowych z wykorzystaniem HTM5, JavaScript, CSS3 i jquery. Łukasz Bartczuk

Przypomnienie o klasach i obiektach

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

Programowanie obiektowe

Podstawy programowania obiektowego

Wstęp do Programowania potok funkcyjny

Podstawy Programowania ELEMENTY PROGRAMU i TYPY DANYCH

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

1 Wstęp. 2 Proste przykłady. 3 Podstawowe elementy leksykalne i typy danych. 6 Opis strukturalny. 7 Moduł testowy (testbench)

Zaawansowany kurs języka Python

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Scala + NetBeans AKA: Nowoczesne obiektowe języki programowania i środowiska programistyczne na przykładzie Scali i środowiska NetBeans

Podstawy programowania w Pythonie

Wstęp do programowania

Wiadomości wstępne Środowisko programistyczne Najważniejsze różnice C/C++ vs Java

DIAGRAMY SYNTAKTYCZNE JĘZYKA TURBO PASCAL 6.0

Programowanie. programowania. Klasa 3 Lekcja 9 PASCAL & C++

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Java: interfejsy i klasy wewnętrzne

Definiowanie własnych klas

Java EE produkcja oprogramowania

Microsoft IT Academy kurs programowania

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

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

Bazy Danych i Usługi Sieciowe

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

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

Programowanie komputerowe. Zajęcia 1

Kompilacja javac prog.java powoduje wyprodukowanie kilku plików o rozszerzeniu.class, m.in. Main.class wykonanie: java Main

Programowanie obiektowe

Język programowania Scala + aktorzy Akka

Programowanie - instrukcje sterujące

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

Programowanie 2. Język C++. Wykład 3.

Pętle while, for, do while, instrukcje break, continue, switch 1. Pętle

PROGRAMOWANIE W ŚRODOWISKU FLASH wykład 2

Język ludzki kod maszynowy

Język programowania zbiór reguł określających, które ciągi symboli tworzą program komputerowy oraz jakie obliczenia opisuje ten program.

JavaScript funkcyjność

Java Programowanie Obiektowe Ćwiczenie 1- wprowadzenie

Programowanie obiektowe

Programowanie w Internecie. Java

Programowanie. Lista zadań nr 15. Na ćwiczenia 11, 19 i 23 czerwca 2008

Paradygmaty programowania

Podstawy i języki programowania

Java Język programowania

Wykresy i interfejsy użytkownika

Programowanie RAD Delphi

Metaprogramowanie w Ruby

Programowanie. Projektowanie funkcje programu tworzenie algorytmu i struktur danych. Programowanie implementacja algorytmu kompilacja programu

Programowanie Komputerów

Funkcje i instrukcje języka JavaScript

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

PODEJŚCIE OBIEKTOWE. Przykład 1 metody i atrybuty statyczne

Python. Wprowadzenie. Jolanta Bachan

Wstęp do Programowania 2

λ parametry. wartość funkcji suma = λ x y. x + y kwadrat = λ x. x * x K.M. Ocetkiewicz, 2008 WETI, PG 2 K.M. Ocetkiewicz, 2008 WETI, PG 3

Języki i metody programowania

Python i programowanie funkcyjne. Python i programowanie funkcyjne czyli nie tylko obiektowość rządzi. OSEC Funkcyjnie w języku Python 1 z 40

Programowanie obiektowe i zdarzeniowe

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Dziedziczenie. dr Jarosław Skaruz

XML extensible Markup Language. część 5

Programowanie Funkcyjne. Marcin Kubica Świder,

Programowanie obiektowe

Zofia Kruczkiewicz, Programowanie obiektowe - java, wykład 2 1

Podstawy programowania w języku C

Kurs rozszerzony języka Python

LibreOffice Calc VBA

Transkrypt:

1 Scala + NetBeans AKA: Nowoczesne obiektowe języki programowania i środowiska programistyczne na przykładzie Scali i środowiska NetBeans (spotkanie 4)

2 For-Comprehensions Przypominają zapytania Ułatwiają stosowanie funkcji wyższego rzędu Przykład: z listy osób wybrać imiona osób mających ponad 20 lat persons filter (p => p.age > 20) map (p => p.name) for (p <- persons if p.age > 20) yield p.name

3 Składnia for ( s ) yield e s to lista generatorów, definicji oraz filtrów (otoczona () lub {) generatory: x <- e, gdzie wyrażenie e jest typu listowego definicje: val x = e filtry: if f, gdzie f to wyrażenie typu Boolean zawsze na początku musi być generator późniejsze generatory iterują szybciej

4 Kilka przykładów że jest prościej Dla danego n znaleźć wszystkie pary 1 <= j < i < n takie że i+j jest pierwsza Poprzednie rozwiązania w dwóch krokach (generujemy pary i,j a potem filtrujemy) List.range(2, n)//generuje wartości od 2 do n-1.map(i => List.range(1, i).map(x => (i, x))).foldright(list[(int, Int)]()) {(xs, ys) => xs ::: ys.filter(pair => isprime(pair._1 + pair._2)) List.range(2, n).flatmap(i => List.range(1, i).map(x => (i, x))).filter(pair => isprime(pair._1 + pair._2)) Z For-Comprehensions for { i <- List.range(2, n) j <- List.range(1, i) if isprime(i+j) yield (i, j) Gdzie def isprime(n: Int) = List.range(2, n) forall (x => n % x!= 0)

5 Kilka przykładów że jest prościej Iloczyn skalarny dwóch wektorów xs i ys Przykładowe rozwiązanie (xs zip ys).map(t => t._1 * t._2).foldleft(0){(x,y) => x + y Z For-Comprehensions sum(for ((x, y) <- xs zip ys) yield x * y)

6 Łamigłówki Problem n królowych Rekurencyjnie sprawdzamy kolejne ustawienia kolejnych królowych Rozwiązanie częściowe reprezentujemy jako listę gdzie ostatnia królowa jest na początku Generujemy pełne listy wszystkich rozwiązań częściowych o zadanej długości def queens(n: Int): List[List[Int]] = { def placequeenincol(col: Int): List[List[Int]] = if (col == 0) List(List()) else for { queens <- placequeens(col 1) row <- List.range(1, n + 1) if issafe(col, row, queens) yield row :: queens placequeens(n)

7 Zapytania Przykładowa baza danych case class Book(title: String, authors: List[String]) Przykładowe dane val books: List[Book] = List( Book("Structure and Interpretation of Computer Programs", List("Abelson, Harold", "Sussman, Gerald J.")), Book("Principles of Compiler Design", List("Aho, Alfred", "Ullman, Jeffrey")), Book("Programming in Modula-2", List("Wirth, Niklaus")), Book("Introduction to Functional Programming"), List("Bird, Richard")), Book("The Java Language Specification", List("Gosling, James", "Joy, Bill", "Steele, Guy", "Bracha, Gilad")))

8 Zapytania c.d. Tytuły wszystkich książek napisanych przez Ullmana for (b <- books; a <- b.authors if a startswith "Ullman") yield b.title Tytuły wszystkich książek, których tytuł zawiera napis Program for (b <- books if (b.title indexof "Program") >= 0) yield b.title Imiona wszystkich autorów co najmniej dwóch książek for (b1 <- books; b2 <- books if b1!= b2; a1 <- b1.authors; a2 <- b2.authors if a1 == a2) yield a1 Z pominięciem duplikatów def removeduplicates[a](xs: List[A]): List[A] = if (xs.isempty) xs else xs.head :: removeduplicates(xs.tail filter (x => x!= xs.head)) lub xs.head :: removeduplicates(for (x <- xs.tail if x!= xs.head) yield x)

9 Foc-Comprehensions przy pomocy innych funkcji For-Comprehensions można przetłumaczyć na map, flatmap, filter for (x <- e) yield e' e.map(x => e') for (x <- e if f; s) yield e for (x <- e.filter(x => f); s) yield e for (x <- e; y <- e ; s) yield e e.flatmap(x => for (y <- e ; s) yield e )

10 Przykład tłumaczenia for { i <- range(2, n) j <- range(1, i) if isprime(i+j) yield (i, j) for (x <- e; y <- e ; s) yield e e.flatmap(x => for (y <- e ; s) yield e ) range(2, n).flatmap( i => for {j <- range(1, i) if isprime(i+j) yield (i, j) range(2, n).flatmap(i => for {j <- range(1,i).filter(j=>isprime(i+j) yield (i,j) for (x <- e if f; s) yield e for (x <- e.filter(x => f); s) yield e for (x <- e) yield e' e.map(x => e') range(2,n).flatmap( i => range(1,i).filter( j => isprime(i+j).map(j => (i,j) ) )

11 Tłumaczenie w drugą stronę object Demo { def map[a, B](xs: List[A], f: A => B): List[B] = for (x <- xs) yield f(x) def flatmap[a, B](xs: List[A], f: A => List[B]): List[B] = for (x <- xs; y <- f(x)) yield y def filter[a](xs: List[A], p: A => Boolean): List[A] = for (x <- xs if p(x)) yield x Jak złożymy tłumaczenia w obie strony, to dostaniemy definicję map przy pomocy map, itd.

12 Pętle for Jest też wersja jedynie wyliczająca wyrażenia, ale nie zbierająca ich wyniku for ( s ) e Przykład: wypisywanie macierzy reprezentowanej jako lista list for (xs <- xss) { for (x <- xs) print(x + "\t") println() Translacja jest prostsza, po trzeba jedynie foreach

13 For-Comprehensions nie tylko dla list Scala zawiera jeszcze inne typy danych wspierające For-Comprehensions Typ danych powinien definiować map, flatmap i filter Należy też zadbać o właściwe typy, np. dla C[A] def map[b](f: A => B): C[B] def flatmap[b](f: A => C[B]): C[B] def filter(p: A => Boolean): C[A] Niestety w Scali nie da się zdefiniować stosownego trait, bo te deklaracje w typie C odwołują się do typu C (jako konstruktora typu stosowanego z różnymi parametrami) Zastosowania: bazy danych, drzewa XML,...

14 Stan Jedyne efekty uboczne, które dotychczas widzieliśmy, to wypisywanie na konsolę Bez efektów ubocznych nie ma znaczenia kolejność wykonywania operacji (wszystkie prowadzą do tego samego wyniku) Innymi słowy czas jest nieistotny Co to stan obiektu/stanowość? Stan to wartość wszystkich atrybutów atrybutów obiektu Obiekt ma stan jeżeli jego zachowanie zależy od historii (np. konto bankowe) Deklarowanie atrybutów var zamiast val var x: String = "abc" Zmienne należy od razu zainicjować (var x: T = _ inicjuje wartością domyślną dla danego typu) Niezainicjowanie atrybutu czyni klasę abstrakcyjną

15 Przykład class BankAccount { private var balance = 0 def deposit(amount: Int) { if (amount > 0) balance += amount def withdraw(amount: Int): Int = if (0 < amount && amount <= balance) { balance -= amount balance else error("insufficient funds") val myaccount = new BankAccount

16 Przykład c.d. scala> myaccount deposit 50 scala> myaccount withdraw 20 res1: Int = 30 scala> myaccount withdraw 20 res2: Int = 10 scala> myaccount withdraw 15 java.lang.runtimeexception: insufficient funds at scala.predef$.error(predef.scala:76) at BankAccount.withdraw(<console>:13) at.<init>(<console>:7) at.<clinit>(<console>) at RequestResult$.<init>(<console>:3) at RequestResult$.<clinit>(<console>) at RequestResult$result(<console>) at sun.reflect.nativemethodaccessorimpl.invoke0(native Method) at sun.reflect.nativemethodacce...

17 Kiedy zmienne wskazują tę samą wartość? Referential transparency jak nie ma przypisań, to następujące definicje dają ten sam efekt: val x = E; val y = E val x = E; val y = x Czy to się zmienia dla val x = new BankAccount; val y = new BankAccount Operational equivalence x oraz y definiują tę samą wartość jeżeli w żadnym eksperymencie nie da się ich odróżnić Test: (1) niech S to dowolny ciąg operacji z x oraz y, (2) niech S' to ciąg otrzymany z S przez zamianę wszystkich wystąpień y na x (3) jeżeli zawsze wyniki S i S' są takie same, to x i y są takie same

18 Przykład Dla val x = new BankAccount; val y = new BankAccount Wynik S > val x = new BankAccount > val y = new BankAccount > x deposit 30 30 > y withdraw 20 java.lang.runtimeexception: insufficient funds Wynik S' > val x = new BankAccount > val y = new BankAccount > x deposit 30 30 > x withdraw 20 10 A jak jest dla val x = new BankAccount; val y = x

19 Imperative control structures Dla wygody Scala ma instrukcje z imperatywnych języków jak C i Java (brakuje break i continue, a zamiast pętli for są For-Comprehensisons) Przykład: x^n=x^(ak*2^k)*...*x^(a0*2^0), gdzie n binarnie to ak...a0 def power(x: Double, n: Int): Double = { var r = 1.0; var i = n; var j = 0 while (j < 32) { r = r * r if (i < 0) r *= x i = i << 1 j += 1 r Zawsze można sobie bez nich poradzić def whileloop(condition: => Boolean)(command: => Unit) { if (condition) { command; whileloop(condition)(command) else ()

20 Przykład: symulacja dyskretnych zdarzeń Mały język do reprezentacji obwodów scalonych Przewody przenoszą sygnały (true/false), które są przetwarzane przez bramki Podstawowe bramki: inverter, and-gate, or-gate Za pomocą podstawowych bramek można budować inne Bramki wprowadzają opóźnienia

21 Przykład c.d. type Action = () => Unit class Wire { private var sigval = false private var actions: List[Action] = List() def getsignal = sigval def setsignal(s: Boolean) = if (s!= sigval) { sigval = s actions.foreach(action => action()) def addaction(a: Action) { actions = a :: actions; a() //case class żeby były domyślne metody dostępu, itp. case class WorkItem(time: Int, action: Action)

22 private type Agenda = List[WorkItem] private var agenda: Agenda = List() private var currenttime = 0 private def insert(ag: Agenda, item: WorkItem): Agenda = if (ag.isempty item.time < ag.head.time) item :: ag else ag.head :: insert(ag.tail, item) def afterdelay(delay: Int)(block: => Unit) { val item = WorkItem(currentTime + delay, () => block) agenda = insert(agenda, item) private def next() { agenda match { case WorkItem(time, action) :: rest => agenda = rest; currenttime = time; action() case List() => def run() { afterdelay(0) { println("*** simulation started ***") while (!agenda.isempty) next()

23 private val InverterDelay = 3; private val OrGateDelay = 1 private val AndGateDelay = 5 def inverter(input: Wire, output: Wire) { def invertaction() { val inputsig = input.getsignal afterdelay(inverterdelay) { output setsignal!inputsig input addaction invertaction def andgate(a1: Wire, a2: Wire, output: Wire) { def andaction() { val a1sig = a1.getsignal val a2sig = a2.getsignal afterdelay(andgatedelay) { output setsignal (a1sig & a2sig) a1 addaction andaction a2 addaction andaction def orgate(a1: Wire, a2: Wire, output: Wire) {...

24 def halfadder(a: Wire, b: Wire, s: Wire, c: Wire) { val d = new Wire val e = new Wire andgate(a, b, c) orgate(a, b, d) inverter(c, e) andgate(d, e, s) a b c d e s --------------------- 0 0 0 0 1 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0

25 def fulladder(a: Wire, b: Wire, cin: Wire, sum: Wire, cout: Wire) { val s = new Wire val c1 = new Wire val c2 = new Wire halfadder(a, cin, s, c1) halfadder(b, s, sum, c2) orgate(c1, c2, cout) a b cin s c1 c2 sum cout 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 1 1 1 1 0 1 0 1 1

26 def probe(name: String, wire: Wire) { wire addaction { () => println(name +" " +currenttime +" new_value=" +wire.getsignal) def main(args: Array[String]) = { val input1, input2, sum, carry = new Wire probe("sum", sum) probe("carry", carry) halfadder(input1, input2, sum, carry) input1 setsignal true; run input2 setsignal true; run sum 0 new_value=false carry 0 new_value=false *** simulation started *** sum 8 new_value=true *** simulation started *** carry 13 new_value=true sum 21 new_value=false

27 Jeszcze o upływie czasu Czy upływ czasu można modelować jedynie funkcjami, których wartości się nie zmieniają Parametr zamieniający się w matematyce przedstawia się jako funkcję f(t) Zmieniającą się zmienną var x: T można zamienić na niezmieniającą się var x: List[T] Wymieniamy pamięć na możliwość zaglądania w przyszłość i przeszłość

28 Strumienie Strumienie dają to samo co listy, ale ogon jest wyliczany tylko jak naprawdę jest potrzebny Przykład definicji Stream.cons(1, Stream.cons(2, Stream.empty)) Przykład użycia def range(start: Int, end: Int): Stream[Int] = if (start >= end) Stream.empty else Stream.cons(start, range(start + 1, end)) Stream.cons wylicza ogon dopiero wtedy gdy jest do niego odwołanie Dostępne są podstawowe metody: head, tail, isempty np. def print(xs: Stream[A]) { if (!xs.isempty) { Console.println(xs.head); print(xs.tail) Dostępna jest też większość pozostałych metod Stream.range(1000, 10000) filter isprime at 1

29 Strumienie Nie ma natomiast operatorów prawego argumentu :: ani ::: Zamiast x :: xs używamy Stream.cons(x, xs) Zamiast xs ::: ys używamy xs append ys.

Leniwość object lazylib { def delay[a](value: => A): Susp[A] = new SuspImpl[A](value) implicit def force[a](s: Susp[A]): A = s() abstract class Susp[+A] extends Function0[A] class SuspImpl[A](lazyValue: => A) extends Susp[A] { private var maybevalue: Option[A] = None override def apply() = maybevalue match { case None => val value = lazyvalue maybevalue = Some(value) value case Some(value) => value override def tostring() = maybevalue match { case None => "Susp(?)" case Some(value) => "Susp(" + value + ")" 30

31 Leniwość c.d. object Main { import lazylib._ def main(args: Array[String]) = { val s: Susp[Int] = delay { println("evaluating..."); 3 println("s = " + s) // show that s is unevaluated println("s() = " + s()) // evaluate s println("s = " + s) // show that the value is saved println("2 + s = " + (2 + s)) // implicit call to force() val sl = delay { Some(3) val sl1: Susp[Some[Int]] = sl val sl2: Susp[Option[Int]] = sl1 // the type is covariant println("sl2 = " + sl2) println("sl2() = " + sl2()) println("sl2 = " + sl2) s = Susp(?) evaluating... s() = 3 s = Susp(3) 2 + s = 5 sl2 = Susp(?) sl2() = Some(3) sl2 = Susp(Some(3))