A-list example -> (find ’Building ’((Course 105) (Building Robinson) (Instructor Fisher))) Robinson -> (val ksf (bind ’Office ’Halligan-242 (bind ’Courses ’(105) (bind ’Email ’comp105-staff ’())))) ((Email comp105-staff) (Courses (105)) (Office Halligan-242)) -> (find ’Office ksf) Halligan-242 -> (find ’Favorite-food ksf) ()
Laws of assocation lists (find k (bind k v l)) = v (find k (bind k’ v l)) = (find k l), provided k != k’ (find k ’()) = ’() --- bogus!
Introduce local names into environment (let ((x1 e1) ... (xn en)) e)
Syntax McCarthy should have used (let ((val x1 e1) ... (val xn en)) e)
Function escapes! -> (define to-the-n-minus-k (n k) (let ((x-to-the-n-minus-k (lambda (x) (- (exp x n) k)))) x-to-the-n-minus-k)) -> (val x-cubed-minus-27 (to-the-n-minus-k 3 27)) -> (x-cubed-minus-27 2) -19
No need to name the escaping function -> (define to-the-n-minus-k (n k) (lambda (x) (- (exp x n) k))) -> (val x-cubed-minus-27 (to-the-n-minus-k 3 27)) -> (x-cubed-minus-27 2) -19
The zero-finder (define findzero-between (f lo hi) ; binary search (if (>= (+ lo 1) hi) hi (let ((mid (/ (+ lo hi) 2))) (if (< (f mid) 0) (findzero-between f mid hi) (findzero-between f lo mid))))) (define findzero (f) (findzero-between f 0 100))
Cube root of 27 and square root of 16 -> (findzero (to-the-n-minus-k 3 27)) 3 -> (findzero (to-the-n-minus-k 2 16)) 4
Lambda questions (define combine (p? q?) (lambda (x) (if (p? x) (q? x) #f))) (define divvy (p? q?) (lambda (x) (if (p? x) #t (q? x)))) (val c-p-e (combine prime? even?)) (val d-p-o (divvy prime? odd?)) (c-p-e 9) == ? (d-p-o 9) == ? (c-p-e 8) == ? (d-p-o 8) == ? (c-p-e 7) == ? (d-p-o 7) == ?
Lambda answers (define combine (p? q?) (lambda (x) (if (p? x) (q? x) #f))) (define divvy (p? q?) (lambda (x) (if (p? x) #t (q? x)))) (val c-p-e (combine prime? even?)) (val d-p-o (divvy prime? odd?)) (c-p-e 9) == #f (d-p-o 9) == #t (c-p-e 8) == #f (d-p-o 8) == #f (c-p-e 7) == #f (d-p-o 7) == #t
An “escaping” function -> (define to-the-n-minus-k (n k) (lambda (x) (- (exp x n) k)))
Closures represent escaping functions Function value representation: j � x : e ( ; � j ) ( � binds the free variables of e ) A closure is a heap-allocated record containing • a pointer to the code • an environment storing free variables f n 7! 3 ; k 7! 27 g ( j ; j ) code for x-to-the-n-minus-k
What’s the closure for conjunction? (define combine (p? q?) (lambda (x) (if (p? x) (q? x) #f)))
Closure for conjunction f p ? � ; q ? ( j ; 7! 7! �g j ) code for (lambda(x)(if ...))
Functions create new functions -> (define o (f g) (lambda (x) (f (g x)))) -> (define even? (n) (= 0 (mod n 2))) -> (val odd? (o not even?)) -> (odd? 3) #t -> (odd? 4) #f
Classic functional technique: Currying -> (val positive? (lambda (y) (< 0 y))) -> (positive? 3) #t -> (val <-c (lambda (x) (lambda (y) (< x y)))) -> (val positive? (<-c 0)) ; "partial application" -> (positive? 0) #f
What’s the algebraic law for ‘curry‘? ... (curry f) ... = ... f ... Keep in mind: All you can do with a function is apply it! (((curry f) x) y) = f (x, y)
No need to curry by hand! ;; curry : binary function -> value -> function -> (val curry (lambda (f) (lambda (x) (lambda (y) (f x y))))) -> (val positive? ((curry <) 0)) -> (positive? -3) #f -> (positive? 11) #t
Exercises -> (map ((curry +) 3) ’(1 2 3 4 5)) ??? -> (exists? ((curry =) 3) ’(1 2 3 4 5)) ??? -> (filter ((curry >) 3) ’(1 2 3 4 5)) ??? ; tricky
Answers -> (map ((curry +) 3) ’(1 2 3 4 5)) (4 5 6 7 8) -> (exists? ((curry =) 3) ’(1 2 3 4 5)) #t -> (filter ((curry >) 3) ’(1 2 3 4 5)) (1 2)
Bonus content: vulnerable variables? -> (val seed 1) -> (val rand (lambda () (set seed (mod (+ (* seed 9) 5) 1024))))) -> (rand) 14 -> (rand) 131 -> (set seed 1) 1 -> (rand) 14
Bonus: Lambda as abstraction barrier! -> (val mk-rand (lambda (seed) (lambda () (set seed (mod (+ (* seed 9) 5) 1024)))))) -> (val rand (mk-rand 1)) -> (rand) 14 -> (rand) 131 -> (set seed 1) error: set unbound variable seed -> (rand) 160
Recommend
More recommend