#lang racket (require racket/trace) (define (sumList L) (if (null? L) 0 (+ (car L) (sumList (cdr L))) ; rezultatul apelului recursiv este argument pentru alt apel )) (trace sumList) (sumList '(1 2 3 4 5)) (define (sumList2 L) (sumList-H L 0)) (define (sumList-H L sumPart) (if (null? L) sumPart (sumList-H (cdr L) (+ sumPart (car L))) ; rezultatul apelului recursiv este întors direct de apelul curent )) (trace sumList2) (trace sumList-H) (sumList2 '(1 2 3 4 5)) (define (sumList3 L . args) ; args este 'lista celorlalte argumente' (let ((sumPart (if (null? args) 0 (car args)))) (if (null? L) sumPart (sumList3 (cdr L) (+ sumPart (car L))) ))) (trace sumList3) (sumList3 '(1 2 3 4 5)) (define (mem e L) ; este recursiv pe coadă dar nu am nevoie de argument suplimentar (cond [(null? L) #f] [(equal? e (car L))] [else (mem e (cdr L))] ; pot folosi condiția #t în loc de else )) (mem 3 '(1 2 3 4 5)) (mem 6 '(1 2 3 4 5)) ; am mai multe apeluri recursive dar sunt pe ramuri diferite (define (evens L) (cond [(null? L) null] [(even? (car L)) (cons (car L) (evens (cdr L)))] [else (evens (cdr L))] )) ; am mai multe apeluri recursive dar fac parte din același apel (define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))) )) (trace fib) (fib 4) ; tupling, fără match ; recursiv pe stivă (define (fib-tp1 n) (if (zero? n) (cons 0 1) (let* ([res (fib-tp1 (sub1 n))] [fn-1 (car res)] [fn (cdr res)] ) ; folosesc o formă de let ca să nu am nevoie de mai multe apeluri (cons fn (+ fn-1 fn)) ) )) (fib-tp1 4) ; tupling, cu match ; recursiv pe stivă (define (fib-tp n) (if (zero? n) (cons 0 1) ; (fib-tp (sub1 n)) -> (fn-1 fn) (match (fib-tp (sub1 n)) ; fac un apel [(cons fn-1 fn) ; dacă rezultatul apelului ; ar putea să fi fost construit cu acest cons, ; atunci leagă fn-1 și fn corespunzător (cons fn (+ fn-1 fn))] ))) (car (fib-tp 4)) ; tupling ; recursiv pe coadă (define (fib-tp-t-h n pair) (if (zero? n) (car pair) (fib-tp-t-h (sub1 n) (cons (cdr pair) (+ (car pair) (cdr pair)))) )) (define (fib-tp-t n) (fib-tp-t-h n (cons 0 1))) (fib-tp-t 4) ; implementare pentru append, ca să pot da trace ; recursiva pe stiva (define (app A B) (if (null? A) B (cons (car A) (app (cdr A) B)))) ; recursivă pe coadă, cu append pentru a adăuga la sfârșit (define (incList-t L Result) (if (null? L) Result (incList-t (cdr L) (app Result (list (add1 (car L))))))) (trace app) (incList-t '(1 2 3 4 5) '()) ; n log n apeluri de app -- fiecare apel din incList parcurge toată lista ; implementări pentru cons și reverse, ca să pot da trace (define cons-1 cons) (define (rev L) (if (null? L) null (cons-1 (car L) (rev (cdr L))))) ; recursivă pe coadă, cu cons și reverse (define (incList-t2 L Result) (if (null? L) (rev Result) (incList-t2 (cdr L) (cons-1 (add1 (car L)) Result)))) (trace cons-1) (incList-t2 '(1 2 3 4 5) '()) ; 2n apeluri de cons -- n apeluri la parcurgere și n apeluri pentru reverse ; continuări (define (sumList-k L k) ; k este o funcție care conține continuarea calculului (if (null? L) (k 0) ; realizez toate prelucrările care mai erau de făcut după terminarea recursivității ; în loc de: ; (+ (car L) (sumList (cdr L))) ; consider separat ; construcția recursivă a rezultatului: (sumList (cdr L)) -> îmi dă um rezultat ; și procesarea ulteioară a rezultatului apelului recursiv: (+ (car L) rezultat) (sumList-k (cdr L) ; apelez pentru restul listei (lambda (res) ; după ce se procesează restul listei, mai vreau să fac și aceste prelucrări asupra rezultatului: (k (+ (car L) res) ; adun rezultatul cu elementul din acest apel ; apoi apelez k din acest apel pentru a face alte prelucrări cerute de apelant )) ) )) (trace sumList-k) (sumList-k '(1 2 3 4 5) identity) ; implementare cu continuări pentru append, recursivă pe coadă ; original: ;(define (app A B) ; (if (null? A) B ; (cons (car A) ; prelucrare rezultat în acest apel ; (app (cdr A) B) ; obținere rezultat din apel recursiv ; ))) ; modific doar la nivel textual: (define (app-k A B k) (if (null? A) (k B) ; adaug peste rezultatul de la capătul recursivității prelucrările din continuare (app-k (cdr A) B ; apel recursiv exact ca în original, dar adaug continuarea (λ (res) (k ; prelucrările de făcut care vin din apelant (cons (car A) res) ; exact prelucrarea originală, dar înlocuind apelul recursiv cu argumentul continuării ))) )) (app-k '(1 2 3) '(4 5 6) identity)