#lang racket ; Mihnea Muraru & Andrei Olaru ;(display "----- Operatori pe fluxuri -----\n") ; definim două modalități de a construi expresii evaluate întârziat. ; pentru fiecare modalitate definim o construcție pack, care construiește ; un obiect care conține calculul care trebuie evaluat întârziat; ; și unpack, care realizează evaluarea unui obiect obținut prin pack. (define-syntax-rule (pack expr) (lambda () expr)) ; închideri ; (delay expr)) ; promisiuni (define unpack (λ (package) (package))) ; închideri ;(define unpack force) ; promisiuni ; ===================================== ; construim funcții pentru fluxuri ; funcții cu același nume sunt disponibile și în biblioteca racket/stream (define-syntax-rule (stream-cons h t) ;; define-syntax-rule definește o construcție nestrictă, ;; deci apelul stream-cons nu va evalua h și t (cons h (pack t))) (define stream-car car) (define (stream-cdr s) (unpack (cdr s))) (define stream-nil '()) (define stream-null? null?) ; =============================== (define (stream-take s n) (cond ((zero? n) '()) ((stream-null? s) '()) (else (cons (stream-car s) (stream-take (stream-cdr s) (- n 1)))))) (define (stream-drop s n) (cond ((zero? n) s) ((stream-null? s) s) (else (stream-drop (stream-cdr s) (- n 1))))) (define (stream-map f s) (if (stream-null? s) s (stream-cons (f (stream-car s)) (stream-map f (stream-cdr s))))) (define (stream-filter f? s) (cond ((stream-null? s) s) ((f? (stream-car s)) (stream-cons (stream-car s) (stream-filter f? (stream-cdr s)))) (else (stream-filter f? (stream-cdr s))))) (define (stream-zip-with f s1 s2) (if (or (stream-null? s1) (stream-null? s2)) stream-nil (stream-cons (f (stream-car s1) (stream-car s2)) (stream-zip-with f (stream-cdr s1) (stream-cdr s2))))) (define (stream-append s1 s2) (if (stream-null? s1) s2 (stream-cons (stream-car s1) (stream-append (stream-cdr s1) s2)))) (define (stream-assoc k s) (cond ((stream-null? s) #f) ((equal? (car (stream-car s)) k) (stream-car s)) (else (stream-assoc k (stream-cdr s))))) (define (list->stream L) (if (null? L) stream-nil (stream-cons (car L) (list->stream (cdr L))))) ; =============================================== (display "----- Definiri de fluxuri -----\n") (display "ones:\n") ; construim o listă infinită de numărul 1, care se numește ones ; (car ones) -> 1 ; (car (cdr ones)) -> 1 ; (car (cdr (cdr ones))) -> 1 ; .... ; (car (cdr (cdr .... (cdr ones) ... ))) -> 1 ; construim o listă infinită de numărul 1, care se numește ones ; (car ones) -> 1 ; (car (cdr ones)) -> 1 ; (car (cdr (cdr ones))) -> 1 ; .... ; (car (cdr (cdr .... (cdr ones) ... ))) -> 1 ;(define ones (cons 1 ones)) ; eroare ;(define ones (letrec ((ones (cons 1 ones))) ones)) ; eroare (ar fi funcționat ; dacă ones era utilizat într-o închidere funcțională) ;(define (ones) (cons 1 (ones))) ; ciclează infinit -> aș vrea ca (ones) să se apeleze doar când am nevoie ;(define ones (cons 1 (λ () ones))) ; inchideri ;(define ones (cons 1 (delay ones))) ; promisiuni (define ones (stream-cons 1 ones)) ; ATENȚIE: există și în racket definit stream-cons & co, în biblioteca racket/stream. ; stream-cons din Racket întoarce un obiect de tip # (car ones) (cdr ones) (equal? ones (stream-cdr ones)) (displayln "naturals:") (define naturals (letrec ((naturalsFrom (λ (start) ; întoarce fluxul start, start+1, start+2... (stream-cons start (naturalsFrom (add1 start))) ))) (naturalsFrom 0))) (define naturals2 (let naturalsFrom ((start 0)) (stream-cons start (naturalsFrom (add1 start))) )) (define naturals3 (stream-cons 0 (stream-map add1 naturals3))) (define naturals4 (stream-cons 0 (stream-zip-with + naturals4 ones))) (stream-take naturals 10) (stream-take naturals2 10) (stream-take naturals3 10) (stream-take naturals4 10) (displayln "even naturals: ") (define even-naturals (stream-zip-with + naturals3 naturals3)) (stream-take even-naturals 10) (define even-naturals2 (stream-zip-with + naturals naturals)) (stream-take even-naturals2 10) (define odd-naturals (stream-zip-with + ones (stream-zip-with + naturals3 naturals3))) (stream-take odd-naturals 10) (display "primes: ") (define primes (let sieve ((numbers (stream-drop naturals 2))) (let ((prime (stream-car numbers))) (stream-cons prime (sieve (stream-filter (λ (n) (not (zero? (remainder n prime)))) numbers )))))) (stream-take primes 10) (display "1000th prime: ") (stream-car (stream-drop primes 999))