PPL Lecture 4 Slides by Yaron Gonen, based on slides by Daniel Deutch and lecture notes by Prof. Mira Balaban
Midterm 2010 (define foo (let((f (lambda(x ) (+ 1 x)))) (lambda(x) (f x)))) תרגמו את ביטוי ה -let לביטוי ה -anonymous lambda מהו מס ' ה -closure שיווצרו ?
Today: High-Order Procedures (continued) Procedures as returned values Delayed computation 4
Procedures as Returned Values Number (+ x y y) [Num -> Num] (lambda (x) (+ x y y)) [Num -> [Num -> Num]] (lambda (y) (lambda (x) (+ x y y))) [Num -> Num] ((lambda (y) (lambda (x) (+ x y y))) 2) Number (((lambda (y) (lambda (x) (+ x y y))) 2) 5)
Example: derive ;Signature: deriv(f dx) ;Type: [[Number -> Number]*Number -> [Number -> Number]] ;Example: for f(x)=x^3, the derivative is the function 3x^2, ;whose value at x=5 is 75. ;Tests: ((deriv cube 0.001) 5) ==> ~75 (define deriv (lambda (f dx) (lambda (x) (/ (- (f (+ x dx)) (f x)) dx))))
Example: derive (define dx 0.001) (define deriv (lambda (f) (lambda (x) (/ (- (f (+ x dx)) (f x)) dx)))) >deriv # >(deriv (lambda (x) (* x x x))) # >((deriv (lambda (x) (* x x x))) 5)
Compile Time vs. Runtime More a question of ‘is it a closure already? Or do we need to evaluate this lambda expression?’ When a closure depends on other closures, it is preferred that these auxiliary closures are created at compile time
Compile Time vs Runtime (define sqr (lambda (x) (* x x))) (sqr 5) ((lambda (x) (* x x)) 5) Compile time Runtime
Example: n th deriv (define nth-deriv (lambda (f n) (lambda (x) (if (= n 0) (f x) ((nth-deriv (deriv f) (- n 1)) x))))) (define dx 0.001) (define deriv (lambda (f) (lambda (x) (/ (- (f (+ x dx)) (f x)) dx)))) reminder
(define nth-deriv (lambda (f n) (lambda (x) (if (= n 0) (f x) ((nth-deriv (deriv f) (- n 1)) x))))) (define nth-deriv (lambda (f n) (if (= n 0) f (lambda (x) ((nth-deriv (deriv f) (- n 1)) x))))) (define nth-deriv (lambda (f n) (if (= n 0) f (nth-deriv (deriv f) (- n 1))))) (define nth-deriv (lambda (f n) (if (= n 0) f (deriv (nth-deriv f (- n 1)))))) >(define five-exp (lambda (x) (* x x x x x))) >(define fourth-deriv-of-five-exp (nth-deriv five-exp 4)) > fourth-deriv-of-five-exp #
Compile time vs Runtime We will always prefer compile-time, but sometimes its not possile (remember f_helper ?)
Delayed Computation With lambda we can delay the computation. We can abuse it to solve hard problems in an elegant way.
and and or special forms (and... ) (or... )
Example (if condition consequence alternative) ==> (or (and condition consequence) alternative)
Example > (define x 0) > (define y 6) > (or (and (zero? x) ) (/ y x)) But what about > (if (zero? x) #f #t) #f > (or (and (zero? x) #f) #t) #t
Example The fixed version: (if condition consequence alternative) ==> ((or (and condition (lambda () consequence)) (lambda () alternative)))
Delayed Computation for obtaining Iterative Process Reminder: recursion stores future computation New method for making iteration of recursion using high-order procedures
Recursive Factorial (define fact (lambda (n) (if (= n 0) 1 (* (fact (- n 1)) n))))
Iterative Factorial (define fact-iter (lambda (n prod) (if (= n 0) prod (fact-iter (- n 1) (* n prod)))))
Iterative Factorial with Delayed Computation (define fact$ (lambda (n cont) (if (= n 0) (cont 1) (fact$ (- n 1) (lambda (res) (cont (* n res)))))))
(fact$ 2 (lambda (x) x)) (fact$ 1 (lambda (res) ((lambda (x) x) (* 2 res)))) (fact$ 0 (lambda (res) ((lambda (res) ((lambda (x) x) (* 2 res))) (* 1 res)))) ((lambda (res) ((lambda (x) x) (* 2 res))) (* 1 res))) 1) ((lambda (res) ((lambda (x) x) (* 2 res))) 1) ((lambda (x) x) 2) 2