#lang racket (require racket/trace) (+ 2 3) ; apel uncurry (define curry+2 ; + de 2 parametri (λ (x) ; la primirea primului parametru va ]ntoarce o altă funcție care aștepată al doilea parametru (λ (y) ; la primirea ultimului parametru, calculăm rezultatul (+ x y) ))) ; apel curry: ;> curry+2 ;# ;> (curry+2 1) ;# ;> ((curry+2 1) 2) ;3 ((curry+2 1) 2) (define curry+3 (λ (x) (λ (y) (λ (z) (+ x y z) )))) (display 'prelucrare-listă:)(newline) (define prelucrare-lista (λ (L f) (if (null? L) '() (cons (f (car L)) (prelucrare-lista (cdr L) f)) ))) (prelucrare-lista '(1 2 3 4 5) (λ (e) (* e 2))) (prelucrare-lista '(1 2 3 4 5) (curry+2 10)) ; adun toate elementele cu o valoare arbitrară ; funcționale (display 'filter:)(newline) (filter odd? '(1 2 3 4 5)) (filter (λ (e) (> (* e e) 10)) '(1 2 3 4 5 6)) (display 'map:)(newline) (map (curry+2 10) '(1 2 3 4 5)) (map (λ (e) (* e e)) '(5 6 7 8 9 10)) (map + '(1 2 3 4) '(10 11 12 13) '(100 200 300 400)) (map cons '(1 2 3) '(a b c)) (map cons '(1 2 3) '(a b ())) ; ! atenție nu este (cons 'a (cons 'b null)) ci este (cons 'a (cons 'b (cons null null))) (map list '(1 2 3) '(a b c) '(#t #f "un string")) (display 'is-in-any-list:)(newline) ; cum știu dacă, fiind dată o valoare, și o listă de liste, ; vreuna dintre liste conține valoarea (fără să le concatenez) ? (define (is-in-any-list v LL) (ormap (λ (L) (not (null? (filter ((curry equal?) v) L)))) LL) ;(ormap (λ (L) (not (null? (filter (λ (e) (equal? v e)) L)))) LL) ; fără curry ;(ormap (λ (L) (not (null? (filter (equal? v) L)))) LL) ; equal? este uncurry ) (is-in-any-list 2 '((a b c) (1 4 5 3 2 6 7) ("un element" "doi element"))) (display 'test-curs:)(newline) (define L1 '(1 2 3 4 5 5 5)) (define L2 '(4 3 2 1 2 6 3)) (filter (λ (p) (> (car p) (cdr p))) (map cons L1 L2)) (apply + '(1 2 3 4)) ;am putea rezulva problema lui (or (map de mai sus cu apply? ; (map dă o listă, iar or are nevoie de argumente individuale) ;(apply or (map ...)) ; dar nu funcționează, pentru că or este funcție nestrictă ; de aceea avem nevoie de ormap (există și andmap) ; vreau suma elementelor pare dintr-o listă (foldl (λ (e ; elementul curent din listă res ; rezultatul parțial al lui fold pentru elementele din listă parcurse până acum ) ; construiesc rezultatul parțial al lui fold pentru elementele parcurse până acum + elementul e (if (even? e) (+ e res) res )) 0 ; valoarea lui fold pentru lista vidă '(1 2 3 4 5 6 7 8) ; lista din care vor fi luat elemente de la stânga la dreapta (și invers pentru foldr) ) ; rezultatul lui fold, rezultatul lui λ / f, v0 și res au toate același tip / aceeași semnificație ; verific dacă o listă este sortată (define (check-sort L) (define f (λ (e ; elementul curent din listă res ; poate fi: ; #t dacă e este primul element și acesta este primul apel de f ; #f dacă am descoperit anterior că lista nu este sortată ; elementul anterior din listă, altfel ) (if (eq? res #t) e ; e este primul element, îl întorc (if res ; testez dacă res este altceva decât #f ; dacă da, în res am elementul anterior (if (> e res) ; testez dacă e este sortat corect față de elementul anterior din listă e ; dacă da, îl întorc #f) ; dacă nu, întorc #f pentru că lista nu este sortată res ; am descoperit într-un apel anterior că lista nu este sortată, res este #f, îl întorc ) ; λ va întoarce element curent, dacă lista este sortată până acum, #f altfel ; (vezi și explicația pentru res de mai sus) ))) ;(trace f) (and (foldl f #t ; trimit inițial #t pentru a semnala primul apel al lui f L) #t)) ; folosesc and pentru a forța valoarea întoarsă la #t (în loc să fie ultimul element din listă) (check-sort '(1 2 3 4 5)) (check-sort '(1 2 6 4 5)) (check-sort '(5 4 3 2 1)) (define M '( (1 2 3 4) (a b c d) (x y z w) )) ; transpusa ; ((1 a x) ; (2 b y) ; (3 c z)) ; când vreau să fac o procesare pe elementele corespondente din ; liste de lungimi egale, folosesc map cu mai multe liste (map (λ (x y z) (display x) (display y) (display z) (newline)) (car M) (cadr M) (caddr M)) (map (λ (x y z) (list x y z)) (car M) (cadr M) (caddr M)) (map list (car M) (cadr M) (caddr M)) ; (list (list 1 a x) (list 2 b y) (list 3 c z)) ; când vreau să aplico funcție (cu număr variabil de argumente) pe un număr de argumente ; necunoscut dinainte, folosesc apply ; (apply f lista-args) (apply map (list list (car M) (cadr M) (caddr M))) ; ^ primul argument pentru map (o valoare de tip funcție, nu se aplică acum) ; ^ construiesc lista de argumente ; vreau o listă cu primul element funcția list, și restul elementelor elementele din M (apply map (cons list M)) ; pot folosi forma lui apply cu mai multe argumente (map precis cu 3 argumente) ; (apply f a L) unde L=e1..en => (f a e1 e2 ... en) (apply map list M) (apply list 'a 'b '(c d e)) (apply list '(a1 a2) 'b '(c d e)) ; apply desface doar ultimul argument (care trebuie să fie o listă) ; toate celelalte argumente (al doilea argument -> penultimul argument inclusiv) rămân neschimbate (let ((f (λ (M-line ; aici primesc o linie din matrice (devine ultima coloană din transpusă acc) ; aici primesc transpusa construită până acum (map (λ (linie-din-transpusa element-din-linie-matrice) ; adaug fiecare element din linia matricei la sfârșitul unei linii din transpusă (append linie-din-transpusa (list element-din-linie-matrice)) ) acc M-line ) ))) (foldl f ; o listă de n elemente; n este câte coloane are matricea M, fiecare element este o listă vidă (map (λ (coloana) null) (car M)) M) ) ; primul apel al lui f va primi (1 2 3) și vreau să îmi producă coloana ; (1) ; (2) ; (3) ; la următoarea iterație, f primește în M-line (a b c) și primește în acc ((1) (2) (3)), trebuie să dea ; (1 a) ; (2 b) ; (3 c) ; v0 conține ; de ce apply și fold nu sunt același lucru (define f+ +) (trace f+) (apply f+ 0 '(1 2 3 4)) ; + aplicat o singură dată, pe 5 argumente 0 1 2 3 4 (display '---)(newline) (foldl f+ 0 '(1 2 3 4)) ; + este aplicat de 4 ori, pe câte 2 argumente de fiecare dată ; let vs let* (let ((a 10) (b 20)) (let ((a 1) ; această variabilă a este vizibilă doar în corpul lui let (al doilea) (b 2) ; această variabilă b este vizibilă doar în corpul lui let (al doilea) (c a) ; nu este încă vizibil a din al doilea let; este vizibil a din primul let (d b) ; nu este încă vizibil b din al doilea let; este vizibil a din primul let ) (list a b c d))) (let ((a 10) (b 20)) (let* ((a 1) ; această variabilă a este vizibilă în corpul lui let și în definițiile pentru b,c,d ; din acest punct a din primul let (cu valoarea 10) nu mai este accesibil (b 2) ; această variabilă b este vizibilă în corpul lui let și în definițiile pentru c,d ; din acest punct b din primul let (cu valoarea 20) nu mai este accesibil (c a) ; se vede a din al doilea let (d b) ; se vede b din al doilea let ) (list a b c d))) ; (λx.(x x) λx.(x x)) ; omega rulează la infinit (opriți cu Ctrl+B): (define runomega (λ () ((λ (x) (x x)) (λ (x) (x x)))))