This shows you the differences between two versions of the page.
|
poo:breviare:breviar-13 [2019/01/07 15:27] carmen.odubasteanu |
poo:breviare:breviar-13 [2026/01/12 08:32] (current) george.tudor1906 [1. Fluxuri (Streams)] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Breviar laborator 13 ====== | ||
| + | ===== Breviar 13 ===== | ||
| - | ===== 1. Design Patterns ===== | + | ==== 1. Fluxuri (Streams) ==== |
| + | === 1.1 Introducere === | ||
| - | ==== Decorator ==== | + | Dennis Ritchie implementează în 1984 primul sistem I/O pe bază de stream în cadrul |
| + | sistemului de operare Unix. Acest concept are la bază crearea unui canal de comunicație | ||
| + | între două entități: **sursă** și **destinație**. Sursa scrie informații în canalul de | ||
| + | comunicație, iar destinația poate să citească aceste date, canalul permițând trecerea | ||
| + | fluxului de date într-o singură direcție. | ||
| + | **Clasificarea fluxurilor:** | ||
| - | De multe ori in cadrul unei aplicatii apare urmatorul scenariu. Aveti de implementat o anumita functionalitate care trebuie sa poate fi extinsa fara sa stiti in momentul proiectarii in ce mod va fi extinsa. | + | După direcția canalului de comunicație: |
| - | De exemplu lucrati la un joc de tipul shooter. Aveti o lista de arme pe care un user le poate achizitiona si utiliza pentru a-si impusca oponentii. La un moment dat observati ca incasarile din joc incep sa scada o data ce alternativele de pe piata ofera mai multe feature-uri pentru armele lor. Pentru a nu da faliment va trebui sa adaugati niste feature-uri noi armelor voastre, dar trebui sa tineti cont ca orice modificare de cod creste fragilitatea si sansa de aparitie a unor bug-uri care initial nu existau. | + | * fluxuri de intrare (pentru citirea datelor) |
| - | Rezolvarea este foarte simpla: O sa creati o clasa abstracta wrapper peste o instanta de arma. Daca de exemplu vreti ca toate armele voastra sa poata fi mortale dar silentioase, creati clasa WeaponSilencer ce implementeaza interfata de baza a armelor si are un obiect de tip arma intern. In metoda fire, in decorator, o sa setati eventual | + | * fluxuri de ieșire (pentru scrierea datelor) |
| - | sunetul jocului mai incet. | + | |
| - | + | ||
| - | {{ :poo:breviare:img1.jpg?600 |}} | + | |
| - | Un alt exemplu la indemana sunt fluxurile din java. | + | După tipul de date pe care le operează: |
| + | * fluxuri de octeți (transfer serial pe 8 biți) | ||
| + | * fluxuri de caractere (transfer serial pe 16 biți) | ||
| - | ''CipherOutputStream cos = new CipherOutputStream(new FileOutputStream( "file" ) , c );'' | + | După acțiunea lor: |
| + | * fluxuri primare de citire/scriere a datelor | ||
| + | * fluxuri pentru procesarea datelor | ||
| - | ''PrintWriter pw = new PrintWriter (new OutputStreamWriter ( cos ) );'' | + | Datorită faptului că există două direcții de comunicare, există două tipuri mari de |
| - | + | stream-uri pentru orice nod de comunicație: **input stream** și **output stream**. | |
| - | ''pw.println ( "Stand and unfold yourself" );'' | + | |
| - | + | ||
| - | ''pw.close( );'' | + | |
| - | + | ||
| - | La baza avem un flux de iesire care va scrie in fisierul "file" niste octeti. | + | |
| - | CipherOutputStream este o clasa decorator si adauga peste fluxul de octeti proprietatea ca acesta este criptat. Deoarece aceasta clasa nu ofera suport de lucru decat pentru octeti avem nevoie de un alt decorator care sa ne permita sa adaugam text in fluxul de iesire. De aceea folosim clasa PrintWriter. | + | |
| - | Observati ca atat PrintWriter, OutputStreamWriter cat si CipherOutputStream sunt doar niste decoratoare ele modificand intr-un anumit mod fluxul, totusi acest flux trebuie sa apara de undeva si de accea toata aceasta decorare trebuie sa aiba la baza un flux instantiat (FileOutputStream). | + | |
| - | + | ||
| - | + | ||
| - | {{ :poo:breviare:img2.jpg |}} | + | |
| - | + | ||
| - | Mapand pe diagrama exemplul nostru, FileOutputStream joaca rolul de componenta concreta, PrintWriter, OutputStreamWriter si CipherOutputStream joaca rolul de decoratoare concrete. | + | |
| - | + | ||
| - | <note important>Atentie: Daca in tot lantul de decorari nu exista un decorator care sa aiba la baza o componenta concreta constructia nu va functiona.</note> | + | |
| - | + | ||
| - | ==== Fluxuri==== | + | |
| - | + | ||
| - | Dennis Ritchie implementeaza in 1984 primul sistem I/O pe baza de stream in cadrul sistemului de operare Unix. Acest concept are la baza crearea unui canal de comunicatie intre doua entitati: sursa si destinatie. Sursa scrie informatii in canalul de comunicatie, iar destinatia poate sa citeasca aceste date, canalul permitand trecerea fluxului de date intr-o singura directie. | + | |
| - | + | ||
| - | Fluxurile pot fi clasificate dupa directia canalului de comunicatie: | + | |
| - | * fluxuri de intrare(pentru citirea datelor), | + | |
| - | * fluxuri de iesire (pentru scrierea datelor); | + | |
| - | dupa tipul de date pe care le opereaza: | + | |
| - | * fluxuri de octeti (transfer serial pe 8 biti), | + | |
| - | * fluxuri de caractere (transfer serial pe 16 biti); | + | |
| - | sau dupa actiunea lor: | + | |
| - | * fluxuri primare de citire/scriere a datelor, | + | |
| - | * fluxuri pentru procesarea datelor. | + | |
| - | + | ||
| - | Datorita faptului ca exista doua directii de comunicare, exista doua tipuri mari de stream-uri pentru orice nod de comunicatie: input stream si output stream. | + | |
| Tastatura ar fi un exemplu de input stream, iar monitorul un output stream. | Tastatura ar fi un exemplu de input stream, iar monitorul un output stream. | ||
| - | Sursa si destinatia nu trebuie sa fie neaparat periferice, ele pot fi si module soft. | + | Sursa și destinația nu trebuie să fie neapărat periferice, ele pot fi și module soft. |
| - | Figure 1: | + | === 1.2 Fluxuri de octeți === |
| - | input stream | + | |
| - | Figure 2: | + | Programele folosesc fluxuri de octeți pentru a citi sau scrie date pe 8 biți (un octet). |
| - | output stream | + | Fluxurile la nivel de octet utilizează două ierarhii având drept clase rădăcină: |
| + | **InputStream** și **OutputStream**. | ||
| - | === Fluxuri de octeti === | + | Cele mai utilizate clase sunt **FileInputStream** și **FileOutputStream**. |
| - | + | ||
| - | Programele folosesc fluxuri de octeti pentru a citi sau scrie date pe 8 biti (un octet). Pentru o mai buna intelegere a acestor clase, se va propune spre analiza implementarea clasei Copy care contine metode care asigura copierea unui fisier text in alt fisier text. | + | |
| + | <code java> | ||
| public class Copy { | public class Copy { | ||
| - | private String input , output ; | + | private String input, output; |
| - | public Copy( String input , String output ) { | + | |
| - | this.input = input ; | + | public Copy(String input, String output) { |
| - | this.output = output ; | + | this.input = input; |
| + | this.output = output; | ||
| } | } | ||
| - | public void copyFile () { | + | |
| - | InputStream in =null; | + | public void copyFile() { |
| - | OutputStream out =null; | + | InputStream in = null; |
| + | OutputStream out = null; | ||
| try { | try { | ||
| - | in =newFileInputStream ( input ) ; | + | in = new FileInputStream(input); |
| - | out =newFileOutputStream ( output ) ; | + | out = new FileOutputStream(output); |
| - | while( in .available() > 0) | + | while (in.available() > 0) |
| - | out.write(in.read ()) ; | + | out.write(in.read()); |
| - | } | + | } catch (FileNotFoundException e) { |
| - | catch( FileNotFoundException e ) { | + | e.printStackTrace(); |
| - | e . printStackTrace () ;} | + | } catch (IOException e) { |
| - | catch( IOException e ) { | + | e.printStackTrace(); |
| - | e . printStackTrace () ;} | + | } finally { |
| - | finally { | + | try { |
| - | try{ | + | if (out != null) out.close(); |
| - | if( out !=null) out.close(); | + | if (in != null) in.close(); |
| - | if( in !=null) in.close() ; | + | } catch (IOException e) { |
| + | e.printStackTrace(); | ||
| } | } | ||
| - | catch( IOException e ) { | ||
| - | e . printStackTrace () ;} | ||
| } | } | ||
| } | } | ||
| } | } | ||
| + | </code> | ||
| - | Fluxurile la nivel de octet utilizeaza doua ierarhii avand drept clase radacina: InputStream si OutputStream. Exista mai multe clase pentru manipularea fluxurilor de octeti, folosite in aceeasi maniera, avand moduri diferite de contructie. Cele mai utilizate clase sunt FileInputStream si FileOutputStream. | + | <note warning> |
| - | + | IMPORTANT! Fișierele text trebuie să se afle în folderul rădăcină al proiectului | |
| - | <note warning> IMPORTANT! Fisierele text trebuie sa se afle in folderul radacina al proiectului care contine clasele care prelucreaza informatia din aceste fisiere. | + | care conține clasele care prelucrează informația din aceste fișiere. |
| </note> | </note> | ||
| - | == Fluxurile de caractere == | + | === 1.3 Fluxuri de caractere === |
| + | |||
| + | Limbajul Java stochează valorile de tip caracter folosind convenții Unicode. | ||
| + | Fluxurile de caractere I/O își translatează automat formatul intern de la setul | ||
| + | de caractere locale. | ||
| - | Limbajul Java stocheaza valorile de tip caracter folosind conventii Unicode. | + | Toate clasele de fluxuri de caractere moștenesc clasele **Reader** și **Writer**. |
| - | Fluxurile de caractere I/O isi translateaza automat formatul intern de la setul de caractere locale. Toate clasele de fluxuri de caractere mostenesc clasele Reader si Writer. Ca si in cazul fluxurilor de octeti, exista clase de fluxuri de caractere specializate pentru operatiile I/O cu fisiere: FileReader si FileWriter. | + | Pentru operațiile I/O cu fișiere: **FileReader** și **FileWriter**. |
| - | Se va oferi un exemplu elocvent pentru a intelege mai bine uzitarea acestor clase. | + | |
| + | <code java> | ||
| public class Read { | public class Read { | ||
| private String input; | private String input; | ||
| - | public Read( String input ) { | + | |
| - | this.input = input ; | + | public Read(String input) { |
| + | this.input = input; | ||
| } | } | ||
| - | public void read () { | + | |
| - | FileReader stream = null; | + | public void read() { |
| + | FileReader stream = null; | ||
| BufferedReader br = null; | BufferedReader br = null; | ||
| - | try{ | + | try { |
| - | stream = new FileReader ( input ) ; | + | stream = new FileReader(input); |
| - | br = new BufferedReader ( stream ) ; | + | br = new BufferedReader(stream); |
| - | String line = br.readLine () ; | + | String line = br.readLine(); |
| while (line != null) { | while (line != null) { | ||
| - | System .out .println (line) ; | + | System.out.println(line); |
| - | line= br.readLine () ; | + | line = br.readLine(); |
| + | } | ||
| + | } catch (FileNotFoundException e) { | ||
| + | e.printStackTrace(); | ||
| + | } catch (IOException e) { | ||
| + | e.printStackTrace(); | ||
| + | } finally { | ||
| + | try { | ||
| + | if (stream != null) stream.close(); | ||
| + | if (br != null) br.close(); | ||
| + | } catch (IOException e) { | ||
| + | e.printStackTrace(); | ||
| } | } | ||
| - | } | ||
| - | catch(FileNotFoundException e ) { | ||
| - | e . printStackTrace () ;} | ||
| - | catch ( IOException e ) { | ||
| - | e . printStackTrace () ;} | ||
| - | finally { | ||
| - | try { | ||
| - | if( stream !=null) { | ||
| - | stream.close() ;} | ||
| - | if( br !=null) { | ||
| - | br.close() ;} | ||
| - | } | ||
| - | catch( IOException e ) { | ||
| - | e . printStackTrace () ;} | ||
| } | } | ||
| - | } | ||
| - | public static void main ( String args [ ] ) { | ||
| - | Read r = new Read("fisier1.in") ; | ||
| - | r.read () ; | ||
| } | } | ||
| } | } | ||
| + | </code> | ||
| - | <note warning>Observatie: Obiectul BufferedReader creaza un flux de intrare a caracterelor cu stocare temporara (si posibilitate de citire a caracterelor sub forma de linii) din fluxul de intrare a caracterelor primit ca parametru (stream), utilizand dimensiunea implicita a tabloului intern. | + | <note> |
| + | Observație: Obiectul BufferedReader creează un flux de intrare a caracterelor cu | ||
| + | stocare temporară (și posibilitate de citire a caracterelor sub formă de linii) | ||
| + | din fluxul de intrare a caracterelor primit ca parametru. | ||
| </note> | </note> | ||
| - | == Fluxuri cu zone tampon == | + | === 1.4 Fluxuri cu zone tampon (Buffer) === |
| - | Pentru un flux I/O fara zone tampon fiecare cerere de citire sau scriere este administrata direct de sistemui de operare. Aceasta face ca programul sa fie mai putin eficient, deoarece fiecare cerere declanseaza accesul la disc, activitate in retea sau alte operatii care consuma timp. | + | Pentru un flux I/O fără zone tampon, fiecare cerere de citire sau scriere este |
| - | Pentru a reduce timpul de procesare a fluxurilor, platforma Java implementeaza fluxuri I/O cu zone tampon. Fuxurile de intrare cu zone tampon citesc datele dintr-o zona de memorie cunoscuta ca tampon (buffer); API –ul de intrare este apelat numai cand tamponul este gol. Similar, fluxurile de iesire scriu datele in | + | administrată direct de sistemul de operare. Aceasta face ca programul să fie mai |
| - | zona de tampon si API-ul de iesire este apelat atunci cand tamponul este plin. | + | puțin eficient, deoarece fiecare cerere declanșează accesul la disc, activitate |
| - | Un program poate converti un flux fara zona tampon intr-un flux cu zona tampon astfel: un obiect de tip flux fara zona tampon este trecut ca argument unui contructor pentru o clasa de tip flux cu zona tampon. | + | în rețea sau alte operații care consumă timp. |
| - | == Fluxuri standard == | + | Pentru a reduce timpul de procesare, platforma Java implementează fluxuri I/O cu |
| + | zone tampon: | ||
| + | * Fluxurile de intrare cu zone tampon citesc datele dintr-o zonă de memorie cunoscută ca **buffer** | ||
| + | * API-ul de intrare este apelat numai când tamponul este gol | ||
| + | * Similar, fluxurile de ieșire scriu datele în zona de tampon și API-ul de ieșire este apelat când tamponul este plin | ||
| - | Limbajul Java pune la dispozitia utilizatorului trei fluxuri standard pentru comunicare cu consola: | + | Un program poate converti un flux fără zonă tampon într-un flux cu zonă tampon |
| - | - fluxul standard de intrare (Standard Input) - folosit pentru citirea datelor; | + | astfel: un obiect de tip flux fără zonă tampon este trecut ca argument unui |
| - | - fluxul standard de iesire (Standard Output) - folosit pentru afisarea datelor; | + | constructor pentru o clasă de tip flux cu zonă tampon. |
| - | - fluxul standard de eroare (Standard Error ) - folosit pentru afisarea erorilor. | + | |
| - | In consecinta, clasa System din pachetul java.lang contine trei referinte statice de urmatoarele tipuri: | + | |
| - | - InputStream in; | + | |
| - | - PrintWriter out; | + | |
| - | - PrintWriter err. | + | |
| - | Astfel, pentru Standard Input exista fluxul System.in, pentru Standard Output se uziteaza System.out, iar pentru Standard Error este System.err. | + | === 1.5 Fluxuri standard === |
| - | <note warning>Observatie: Nu este necesara instantierea acestor trei stream-uri, deoarece ele se deschid automat inaintea executiei aplicatiei. Celelalte stream-uri se deschid in momentul crearii lor, prin apelul constructorului clasei corespunzatoare. | + | Limbajul Java pune la dispoziția utilizatorului trei fluxuri standard pentru |
| - | De asemenea, acestea nici nu inchid prin apelul metodei close().</note> | + | comunicare cu consola: |
| - | Pentru inceput, se va prezenta un exemplu in care se uziteaza obiecte de tip InputStreamReader, BufferedReader si o instanta statica din clasaSystem. | + | | **Flux** | **Descriere** | **Referință** | |
| - | Clasa Suma contine o metoda care citeste de la tastatura doua numere intregi, iar, pentru simplitate, acestea sunt citite ca obiecte de tip String, urmand a fi convertite. | + | | Standard Input | pentru citirea datelor | System.in (InputStream) | |
| + | | Standard Output | pentru afișarea datelor | System.out (PrintWriter) | | ||
| + | | Standard Error | pentru afișarea erorilor | System.err (PrintWriter) | | ||
| + | <note> | ||
| + | Observație: Nu este necesară instanțierea acestor trei stream-uri, deoarece ele | ||
| + | se deschid automat înaintea execuției aplicației. De asemenea, acestea nici nu | ||
| + | se închid prin apelul metodei close(). | ||
| + | </note> | ||
| + | |||
| + | **Exemplu cu InputStreamReader și BufferedReader:** | ||
| + | |||
| + | <code java> | ||
| public class Suma { | public class Suma { | ||
| - | int a, b ; | + | int a, b; |
| - | public void read () { | + | |
| - | InputStreamReader stream= null; | + | public void read() { |
| - | BufferedReader br= null; | + | InputStreamReader stream = null; |
| - | try{ | + | BufferedReader br = null; |
| - | stream = new InputStreamReader ( System.in ) ; | + | try { |
| - | br = new BufferedReader ( stream ) ; | + | stream = new InputStreamReader(System.in); |
| - | String line = br.readLine () ; | + | br = new BufferedReader(stream); |
| - | a = Integer.parseInt ( line ) ; | + | String line = br.readLine(); |
| - | line = br.readLine () ; | + | a = Integer.parseInt(line); |
| - | b = Integer.parseInt ( line ) ; | + | line = br.readLine(); |
| - | } | + | b = Integer.parseInt(line); |
| - | catch( FileNotFoundException e ) { | + | } catch (IOException e) { |
| - | e.printStackTrace () ;} | + | e.printStackTrace(); |
| - | catch ( IOException e ) { | + | } finally { |
| - | e . printStackTrace () ;} | + | try { |
| - | finally{ | + | if (stream != null) stream.close(); |
| - | try{ | + | if (br != null) br.close(); |
| - | if( stream !=null) | + | } catch (IOException e) { |
| - | stream.close() ; | + | e.printStackTrace(); |
| - | if ( br != null) | + | |
| - | br.close() ; | + | |
| } | } | ||
| - | catch ( IOException e ) { | ||
| - | e . printStackTrace () ;} | ||
| } | } | ||
| } | } | ||
| } | } | ||
| + | </code> | ||
| - | In al doilea exemplu, se va prezenta citirea de la tastatura a doua numere intregi,utilizand un obiect de tip | + | **Exemplu cu Scanner:** |
| - | Scanner. Aceasta clasa pune la dispozitie o serie de metode pentru citirea celor mai importante tipuri predefinite de date din limbajul Java. | + | |
| + | <code java> | ||
| public class Test { | public class Test { | ||
| - | public static void main( String args[ ]) throws Exception { | + | public static void main(String args[]) throws Exception { |
| - | Scanner in = new Scanner ( System . in ) ; | + | Scanner in = new Scanner(System.in); |
| - | int a, b ; | + | int a, b; |
| - | a = in . nextInt () ; | + | a = in.nextInt(); |
| - | b = in . nextInt () ; | + | b = in.nextInt(); |
| - | int result; | + | int result = a + b; |
| - | result = a + b ; | + | System.out.println(a + " + " + b + " = " + result); |
| - | System.out.println ( a + " + " + b + " = " + result) ; | + | in.close(); |
| - | in.close() ; | + | |
| } | } | ||
| } | } | ||
| + | </code> | ||
| + | |||
| + | ==== 2. Funcționale ==== | ||
| + | |||
| + | === 2.1 Introducere === | ||
| + | |||
| + | În paradigma funcțională, funcțiile sunt valori de ordinul 1 ce pot fi manipulate | ||
| + | ca orice altă valoare. **Funcționalele** sunt funcții care manipulează alte funcții, | ||
| + | primindu-le ca argumente sau returnându-le ca rezultat. | ||
| + | |||
| + | === 2.2 Lista funcționalelor === | ||
| + | |||
| + | == foldl(function, init, list) == | ||
| + | |||
| + | Returnează rezultatul aplicării funcției **function** pe rând asupra unui element | ||
| + | din listă și a unui acumulator **init**. Ordinea folosirii elementelor din listă | ||
| + | este de la **stânga la dreapta**. | ||
| + | |||
| + | <code> | ||
| + | foldl(f(x, y) = x + y, 5, [0, 1, 2, 3]) | ||
| + | = f(f(f(f(5, 0), 1), 2), 3) | ||
| + | = f(f(f(5, 1), 2), 3) | ||
| + | = f(f(6, 2), 3) | ||
| + | = f(8, 3) | ||
| + | = 11 | ||
| + | </code> | ||
| + | |||
| + | == foldr(function, init, list) == | ||
| + | |||
| + | Are un comportament similar cu foldl, însă ordinea folosirii elementelor din listă | ||
| + | este de la **dreapta la stânga**. | ||
| + | |||
| + | <code> | ||
| + | foldr(f(x, y) = y, 4, [0, 1, 2, 3]) | ||
| + | = f(0, f(1, f(2, f(3, 4)))) | ||
| + | = f(0, f(1, f(2, 4))) | ||
| + | = f(0, f(1, 4)) | ||
| + | = f(0, 4) | ||
| + | = 0 | ||
| + | </code> | ||
| + | |||
| + | == map(function, list) == | ||
| + | |||
| + | Returnează lista rezultatelor aplicării unei funcții **f** asupra fiecărui element | ||
| + | dintr-o listă. | ||
| + | |||
| + | <code> | ||
| + | map(f(x) = 2*x, [0, 1, 2, 3]) => [0, 2, 4, 6] | ||
| + | </code> | ||
| + | |||
| + | == filter(predicat, list) == | ||
| + | |||
| + | Returnează lista elementelor dintr-o listă care satisfac un predicat **p**. | ||
| + | Un predicat este o funcție care are un rezultat de tip Boolean. | ||
| + | |||
| + | <code> | ||
| + | filter(f(x) = x % 2 == 0, [0, 1, 2, 3]) => [0, 2] | ||
| + | </code> | ||
| + | |||
| + | == reduce(function, list) == | ||
| + | |||
| + | Aplică funcția pentru primele două elemente din listă, apoi pentru rezultatul | ||
| + | obținut anterior și următorul element și tot așa. | ||
| + | |||
| + | <code> | ||
| + | reduce(f(x, y) = x + y, [47, 11, 42, 13]) | ||
| + | = f(f(f(47, 11), 42), 13) | ||
| + | = f(f(58, 42), 13) | ||
| + | = f(100, 13) | ||
| + | = 113 | ||
| + | </code> | ||
| + | |||
| + | == all(predicat, list) == | ||
| + | |||
| + | Primește un predicat și verifică dacă **toate** elementele din listă satisfac predicatul. | ||
| + | |||
| + | <code> | ||
| + | all(f(x) = x > 0, [0, 1, 2, 3]) => False (0 nu e > 0) | ||
| + | all(f(x) = x >= 0, [0, 1, 2, 3]) => True | ||
| + | </code> | ||
| + | |||
| + | == any(predicat, list) == | ||
| + | |||
| + | Primește un predicat și verifică dacă există **cel puțin un element** în listă | ||
| + | care satisface predicatul. | ||
| + | |||
| + | <code> | ||
| + | any(f(x) = x < 0, [1, 2, 3, 4]) => False | ||
| + | any(f(x) = x % 2 == 0, [1, 2, 3]) => True (2 e par) | ||
| + | </code> | ||
| + | |||
| + | === 2.3 Rezumat funcționale === | ||
| + | |||
| + | | **Funcțională** | **Descriere** | **Exemplu** | | ||
| + | | **foldl** | Agregare stânga→dreapta cu acumulator | foldl(+, 0, [1,2,3]) = 6 | | ||
| + | | **foldr** | Agregare dreapta→stânga cu acumulator | foldr(-, 0, [1,2,3]) = 2 | | ||
| + | | **map** | Transformă fiecare element | map(x→x*2, [1,2]) = [2,4] | | ||
| + | | **filter** | Păstrează elementele care satisfac predicatul | filter(par, [1,2,3]) = [2] | | ||
| + | | **reduce** | Agregare fără acumulator inițial | reduce(+, [1,2,3]) = 6 | | ||
| + | | **all** | Toate satisfac predicatul? | all(>0, [1,2]) = True | | ||
| + | | **any** | Există cel puțin unul care satisface? | any(<0, [1,2]) = False | | ||
| + | |||