;;; Day 5 code, Michael Wollowski (define (rl) (load "day5.ss")) ;;; Using let expressions to solve a problem in an imperative style (define pythagoras (lambda (x y) (let ([x-squared (* x x)] [y-squared (* y y)]) (let ([hypotenuse (sqrt (+ x-squared y-squared))]) hypotenuse)))) ;;; This does not work, because of scope issues: x-squared and y-squared ;;; are not defined yet when we try to use them to calculate hypothenuse (define pythagoras (lambda (x y) (let ([x-squared (* x x)] [y-squared (* y y)] [hypotenuse (sqrt (+ x-squared y-squared))]) hypotenuse))) ;;; Let's convert the above code to lambda-let expressions: (define pythagoras (lambda (x y) ((lambda (x-squared y-squared hypothenuse) hypothenuse) (* x x) (* y y) (sqrt (+ x-squared y-squared))))) ;;; Ooooh, look at that! Let* expressions. (define pythagoras (lambda (x y) (let* ([x-squared (* x x)] [y-squared (* y y)] [hypotenuse (sqrt (+ x-squared y-squared))]) hypotenuse))) ;;; A let* is a nested let expression: (define pythagoras (lambda (x y) (let ([x-squared (* x x)]) (let ([y-squared (* y y)]) (let ([hypotenuse (sqrt (+ x-squared y-squared))]) hypotenuse))))) ;;; checking scope by translating it into lambda-app expressions: (define pythagorasLambda (lambda (x y) ((lambda (x-squared) ((lambda (y-squared) ((lambda (hypothenuse) hypothenuse) (sqrt (+ x-squared y-squared)))) (* y y))) (* x x)))) (define fac (lambda (n) (facT n 1))) (define facT (lambda (n accu) (if (= n 0) accu (facT (-n 1) (* n accu))))) ;;; Local functions enable information hiding (define fac1 (lambda (n) (let ([fact (lambda (n accu) (if (= n 0) accu (fact (- n 1) (* n accu))))]) (fact n 1)))) ;;; The above code does not work, due to scope issues: (define fac2 (lambda (n) ((lambda (fact) (fact n 1)) (lambda (n accu) (if (= n 0) accu (fact (- n 1) (* n accu))))))) ;;; Letrec fixes that: (define fac3 (lambda (n) (letrec ([fact (lambda (n accu) (if (= n 0) accu (fact (- n 1)(* n accu))))]) (fact n 1)))) ;;; Fac with named let: ;;; Notice the shadowing of the outer n by the inner n (define fac-named-let (lambda (n) (let loop ([n n][accu 1]) (if (zero? n) accu (loop (- n 1) (* accu n)))))) ;(define odd? ; (lambda (n) ; (if (zero? n) ; #f ; (even? (- n 1))))) ;(define even? ; (lambda (n) ; (if (zero? n) ; #t ; (odd? (- n 1))))) ;;; Trick question: Why does the following code work? (define odd-dumb? (lambda (n) (let ([odd? (lambda (n) (if (zero? n) #f (even? (- n 1))))] [even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))]) (odd? n))))