#lang racket ; pentru ce folosim de obicei prelucrări iterative pe o colecție? ; modificăm date ; selectăm elemente ; iterăm ; obținem un rezultat peste întreaga colecție (sumă, maxim) ; verificare prezență sau absența unui element ; afișare (define L '(6 5 8 3 2 9 5 7)) ; afișare (map display L) (for-each display L) (newline) ; "modificăm" (map (λ (e) (if (equal? e 3) (* 2 e) e)) L) ; înlocuim pe 3 cu dublul său ; sumă (foldl + 0 L) ; maxim (foldl (λ (e max) (if (> e max) e max)) (car L) (cdr L)) ; selectăm anumite elemente din listă (filter even? L) ; prelucrare iterativă pe mai multe liste (map list '(1 2 3 4) '(a b c d) '(#t #f #f #t)) ; filtrare pentru intersecția cu altă listă (filter (λ (e) (member e '(1 2 3))) L) (define (map-with-fold f L) ;(foldl (foldr (λ (e acc) ; (append acc (list (f e))) ; dacă folosesc foldl (cons (f e) acc) ; dacă folosesc foldr ) '() L)) (map-with-fold add1 L) (define (filter-with-fold f L) (foldr (λ (e acc) (if (f e) (cons e acc) acc )) '() L)) (filter-with-fold even? L) ; sortăm (define (sort-with-fold L) (foldl (λ (e sorted) ; fiecare element e în inserez la poziția corectă în lista restului elementelor, sortate (append (filter (λ (x) (<= x e)) sorted) (list e) (filter (λ (x) (> x e)) sorted) )) '() L)) (sort-with-fold L) ; curry / uncurry ; funcția member, în formă curry (define curry-member (λ (e) (λ (L) (member e L) ))) ((curry-member 3) '(1 2 3 4 5)) ; curry transformă o funcție de 2 args în formă uncurry în funcție în formă curry (define (curry2 f2arg) ; f2arg are 2 args și este în formă uncurry -- este apelată ca (f2arg x y) ; dacă curry2 primește un parametru f, atunci întoarce o funcție de arg1... (λ (arg1) ; ...care când primește un argument (primul argument pentru f2arg), întoarce o funcție de arg2... (λ (arg2) ; ... care când primește un argument (al doilea argument pentru f2arg), aplică pe f2arg pe arg1 și arg2 (f2arg arg1 arg2)))) (curry2 member) ; funcția member, transformată în formă curry ((curry2 member) 3) ; funcția member, transformată în formă curry, aplicată _parțial_ pe un argument ; rămâne să mai primească un argument pentru a se aplica de fapt funcția + (((curry2 member) 3) '(1 2 3 4 5)) ; reluăm sort, folosim aplicare parțială a operatorilor de inegalitate, transformați în formă curry (define (sort-with-fold2 L) (foldl (λ (e sorted) (append (filter ((curry2 >=) e) sorted) ; filter (>= e) sorted (list e) (filter ((curry2 <) e) sorted) )) '() L)) (sort-with-fold2 L) (map ((curry2 +) 5) L) ; map (+5) L ; ((curry2 +) 5) -- funcție de 1 arg care își adună argumentul cu 5 ; flip inversează ordinea în care o funcție curry își primește argumentele (define (flip f2curry) (λ (a) (λ (b) ((f2curry b) a)))) ; filter pentru intersecție (filter ((flip curry-member) '(1 2 3)) L) (map ((curry cons) 'pre) '(a b c d)) (map ((flip (curry cons)) 'post) '(a b c d)) (apply + L) (define M '((1 2 3) (4 5 6) (7 8 9) (10 11 12))) ; suma pe linii (map (λ (linie) (apply + linie)) M) (map ((curry apply) +) M) ; suma pe coloane (map + (car M) (cadr M) (caddr M) (cadddr M)) (apply map + M) ; (map + linia1 linia2 ...) ; ATENȚIE: apply și fold fac lucruri complet diferite (apply + 0 '(1 2 3 4)) ; aplică + o singură dată, pe 5 argument (foldl + 0 '(1 2 3 4)) ; aplică + de 4 ori, pe câte 2 argumente