(load "util.scm") (display "\nex-3.9 - draw factorial evaluation model\n") (display "[see comments]\n") (define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1))))) (define (factorial n) (fact-iter 1 1 n)) (define (fact-iter product counter max-count) (if (> counter max-count) product (fact-iter (* counter product) (+ counter 1) max-count))) ; Nothing to special. I drew this out in my 2020 notebook on page 203. ; The drawing in the Scheme-Wiki is nice too: ; http://community.schemewiki.org/?sicp-ex-3.9 ; RECURSIVE VERSION ; ; global ________________________ ; env | other var. | ; ------->| factorial : * | ; | | | ; |_____________|_________| ; | ^ ; | | ; variables : n ; body: (if (= n 1) 1 (* n (factorial (- n 1)))) ; ; (factorial 6) ; ; _______ ^ ; E1 -->| n : 6 |___________| GLOBAL ; ------- ; (* 6 (factorial 5)) ; _______ ^ ; E2 -->| n : 5 |___________| GLOBAL ; ------- ; (* 5 (factorial 4)) ; _______ ^ ; E3 -->| n : 4 |___________| GLOBAL ; ------- ; (* 4 (factorial 3)) ; _______ ^ ; E4 -->| n : 3 |___________| GLOBAL ; ------- ; (* 3 (factorial 2)) ; _______ ^ ; E5 -->| n : 2 |___________| GLOBAL ; ------- ; (* 2 (factorial 1)) ; _______ ^ ; E6 -->| n : 1 |___________| GLOBAL ; ------- ; 1 ; ; ITERATIVE VERSON ; ; global ___________________________________ ; env | other var. | ; ------->| factorial : * | ; | fact-iter : | * | ; |_____________|_______________|____| ; | ^ | ^ ; | | | | ; | | variable : (product counter max-count) ; | | body: (if (> counter max-count) ; | | prod ; | | (fact-iter (* counter product) ; | | (+ counter 1) ; | | max-count)) ; | | ; variable: n ; body: (fact-iter 1 1 n) ; ; (factorial 6) ; ; _______ ^ ; E1 -->| n : 6 |_____________| GLOBAL ; ------- ; (fact-iter 1 1 n) ; ; E2 -->| product : 1 ^ ; | counter : 1 ___| GLOBAL ; | max-count : 6 ; (fact-iter 1 2 6) ; ; E3 -->| product : 1 ^ ; | counter : 2 ____| GLOBAL ; | max-count : 6 ; (fact-iter 2 3 6) ; ; E4 -->| product : 2 ^ ; | counter : 3 _____| GLOBAL ; | max-count : 6 ; (fact-iter 6 4 6) ; ; E5 -->| product : 6 ^ ; | counter : 4 _____| GLOBAL ; | max-count : 6 ; (fact-iter 24 5 6) ; ; E6 -->| product : 24 ^ ; | counter : 5 _____| GLOBAL ; | max-count : 6 ; (fact-iter 120 6 6) ; ; E7 -->| product : 120 ^ ; | counter : 6 _____| GLOBAL ; | max-count : 6 ; (fact-iter 720 7 6) ; ; E8 -->| product : 720 ^ ; | counter : 7 _____| GLOBAL ; | max-count : 6 ; 720 (display "\nex-3.10 - nested lambdas frames\n") (define (make-withdraw initial-amount) (let ((balance initial-amount)) (lambda (amount) (display initial-amount) (newline) (display balance) (newline) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")))) (define W1 (make-withdraw 100)) (W1 20) (W1 20) (W1 20) ; The let binding creates a second lambda procedure and consequently a ; second frame. We can use display to show that both initial-amount and balance ; are available via the first and second frame. However, only balance is ; affected by calls to the return procedure, as we can see. ; This is the ascii diagram from the Scheme community wiki: ; global->| make-withdraw : * | ; env. | W1 : * | | ; -------|---^-----|---^- ; | | | | ; | | parameter: initial-mount ; | | body: ((lambda (balance) ((...))) initial-mount) ; | | ; | _|___Frame_A__________ ; | | initial-mount : 100 |<- E0 ; | -^-------------------- ; | | ; | _|__________Frame_B______ ; | | balance : initial-mount | <- E1 ; | -^----------------------- ; | | ; parameter: amount ; body: (if (>= balance amount) ... ) ; ; (W1 50) ; ; Set! will affect Frame B, initial-mount remains unchanged in Frame A. ; _______________________ ; global->| make-withdraw : * | ; env. | W1 : * | | ; -------|---^-----|---^- ; | | | | ; | | parameter: initial-mount ; | | body: ((lambda (balance) ((...))) initial-mount) ; | | ; | _|___Frame_A__________ ; | | initial-mount : 100 |<- E0 ; | -^-------------------- ; | | ; | _|__________Frame_B___ ; | | balance : 50 | <- E1 ; | -^-------------------- ; | | ; parameter: amount ; body: (if (>= balance amount) ... ) (display "\nex-3.11\n") ; Relatively clear to me what is going on. Let's move on. (display "[see schemewiki]\n")