#lang racket (define-namespace-anchor a) (define ns (namespace-anchor->namespace a)) ;; clasic (define prod1 (λ (x y) ; în y primesc o valoare (displayln "prod") (if x (* y (+ y 1)) 0))) (define test1 (λ (cond) (let ((calcul 5)) (prod1 cond (and (display "calc ") calcul)))) ; în al doilea argument, prod primește valoarea 5, ; care se calculează înainte de apelul lui prod ) (test1 #f) (test1 #t) (displayln "------ ^ direct") ; dar îmi doresc să obțin ; prod ; calc prod ;; quote + eval (define prod2 (λ (x y) ; în y primesc o secvență de literali (displayln "prod") (if x (* (eval y ns) (+ (eval y ns) 1)) 0))) ; eval necesită un spațiu de nume în care să evalueze expresia ; aici, am dat spațiul de nume global; ; dar nu văd simbolul "calcul" ca identificator în acest context ; o soluție ar fi să transmitem și spațiul de nume local ca argument (define test2 (λ (cond) (let ((calcul 5)) (prod2 cond '(and (display "calc ") calcul)))) ; în al doilea argument, prod primește expresia "(and (display "calc ") calcul)", fără context ; astfel că simbolul "calcul" nu va fi legat la nimic în momentul lui eval ; alternativ, contruiesc, textual, expresia calculului, ; dar evaluez argumentele pe care altfel nu le văd în prod ) ;(test2 #f) (test2 #t) (displayln "------ ^ quote") ; (paranteză ; ' quote ; ` quasiquote ; , unquote ; ) ;; inchidere funcțională (define prod3 (λ (x y) ; în al doilea argument, prod primește o închidere funcțională ; < (λ () (and (display "calcul ") calcul)) ; { calcul <- 5 } > (displayln "prod") (if x (* (y) (+ (y) 1)) 0))) (define test3 (λ (cond) (let ((calcul 5)) (prod3 cond (λ () (and (display "calc ") calcul))))) ) (test3 #f) (test3 #t) (displayln "------ ^ lambda") ;; promisiuni (define prod4 (λ (x y) ; în y primesc o promisiune (displayln "prod") ; în al doilea argument, prod primește o promisiune ; < (and (display "calcul ") calcul) ; { calcul <- 5 } ; fără valoare calculată > ; după primul force, promisiunea devine ; < (and (display "y ") calcul) ; { calcul <- 5 } ; valoare calculată: 5> ; la force-uri ulterioare pe această promisiune, se întoarce direct valoarea calculată (if x (* (force y) (+ (force y) 1)) 0))) (define test4 (λ (cond) (let ((calcul 5)) (prod4 cond (delay (and (display "calc ") calcul))))) ) (test4 #f) (test4 #t) (displayln "------ ^ promise") (define time (delay (current-seconds))) ; (displayln "------") ;; ============================================================================ ;; creez un macro pentru a abstractiza mecanismul de întârziere ;; cu inchideri ;(define-syntax-rule (pack computation) (λ () computation) ) ;(define (unpack package) (package) ) ;; cu promisiuni (define-syntax-rule (pack computation) (delay computation) ) (define (unpack package) (force package) )