370 likes | 460 Views
PPL. Lecture 3 Slides by Dr. Daniel Deutch , based on lecture notes by Prof. Mira Balaban. Scope and binding. Block Structure. f(x,y,z) = (x+y) 2 + (x+z) 2. Lets write a procedure that given x, y, and z computes. (define (sum-and-square x y) (square (+ x y))).
E N D
PPL Lecture 3 Slides by Dr. Daniel Deutch, based on lecture notes by Prof. Mira Balaban
Block Structure f(x,y,z) = (x+y)2 + (x+z)2 Lets write a procedure that given x, y, and z computes (define (sum-and-square x y) (square (+ x y))) (define (f x y z) (+ (sum-and-square x y) (sum-and-square x z)))
Block structure (cont.) Lets write a procedure that given inputs x, y, and z, computes f(x,y,z) = (x+y)2 + (x+z)2 while keeping sum-and-square private to f (hidden from the outside world): (define (f x y z)(define (sum-and-square x y) (square (+ x y))) (+ (sum-and-square x y) (sum-and-square x z))) We discourage the use of define inside a function, and will later see a better way (LET) of hiding sum-and-square!
(define (sum-and-square 1 2) (square (+ 1 2))) (+ (sum-and-square 1 2) (sum-and-square 1 3))) We still need to clarify the substitution model.. (define (f x y z)(define (sum-and-square x y) (square (+ x y))) (+ (sum-and-square x y) (sum-and-square x z))) ==> (f 1 2 3)
(define (f x y z)(define (sum-and-square x y) (square (+ x y))) (+ (sum-and-square x y) (sum-and-square x z))) x,y,z x,y Bounded variables and scope A procedure definition binds its formal parameters The scope of the formal parameter is the body of the procedure. This is called lexical scoping
The value of a numeral: number The value of a built-in operator: machine instructions to execute The value of any name: the associated object in the environment • To Evaluate a combination: (other than special form) • Evaluate all of the sub-expressions in any order • Apply the procedure that is the value of the leftmost sub-expression to the arguments (the values of the other sub-expressions) Evaluation of An Expression (refined) To Apply a compound procedure: (to a list of arguments) Evaluate the body of the procedure with the formal parameters replaced by the corresponding actual values. Do not substitute for occurrences that are bound by an internal definition.
(define (sum-and-square x y) (square (+ x y))) (+ (sum-and-square 1 2) (sum-and-square 1 3))) The refined substitution model (define (f x y z)(define (sum-and-square x y) (square (+ x y))) (+ (sum-and-square x y) (sum-and-square x z))) ==> (f 1 2 3)
Sum-and-square Proc (x y) (square (+ x y)) (+ (sum-and-square 1 2) (sum-and-square 1 3))) The refined substitution model ==> (f 1 2 3) (define (sum-and-square x y) (square (+ x y))) (+ (sum-and-square 1 2) (sum-and-square 1 3)))
(define initial-guess 1.0) (define precision 0.0001) (define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x))) (define (good-enough? guess x) (< (abs (- (square guess) x)) precision)) (define (improve guess x) (average guess (/ x guess))) (define (sqrt x) (sqrt-iter initial-guess x))
Good programming Style • 1. Divide the task to well-defined, natural, and • simple sub-tasks. • E.g: good-enough? and improve. • Rule of thumb : If you can easily name it, it does a well-defined task. 2. Use parameters. E.g.: precision, initial-guess. 3. Use meaningful names.
Procedural abstraction • It is better to: • Export only what is needed • Hide internal details. The procedure SQRT is of interest for the user. The procedure improve-guessis an internal detail. • Exporting only what is needed leads to: • A clear interface • Avoids confusion
Rewriting SQRT (Block structure) (define (sqrt x) (define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x))) (define (good-enough? guess x) (< (abs (- (square guess) x)) precision)) (define (improve guess x) (average guess (/ x guess))) (define initial-guess 1.0) (define precision 0.00001) (sqrt-iter initial-guess x))
Further improving sqrt Note that in every application of sqrt we substitute for x the same value in all subsequent applications of compound procedures ! Therefore wedo not have to explicitly pass x as a formal variable to all procedures. Instead, can leave it unbounded (“free”).
SQRT again, taking advantage of the refined substitution model (define (sqrt x) (define (good-enough? guess) (< (abs (- (square guess) x)) precision)) (define (improve guess) (average guess (/ x guess))) (define (sqrt-iter guess) (if (good-enough? guess) guess (sqrt-iter (improve guess)))) (define initial-guess 1.0) (define precision 0.00001) (sqrt-iter initial-guess))
Lexical Scoping - again The lexical scoping rules means that the value of a variable which is unbounded (free) in a procedure f is taken from the procedure in which f was defined. It is also called static scoping
Another example for lexical scope (define (proc1 x) (define (proc2 y) (+ x y)) (define (proc3 x) (proc2 x)) (proc3 (* 2 x))) (proc1 4) proc1.x = 4 (proc3 8) proc3.x = 8 (proc2 8) proc2.y = 8 proc2.x=proc1.x=4 12
LET • For internal definitions, where possible we will prefer using let rather than define • Functional programming • Limits the scope of temporary definitions in a natural way • Problematic when the internally defined function is recursive • Why? • To be discussed in the Practical Session
High-Order Procedures • In functional programming (hence, in Scheme) procedures have a first class status: 1. Can be pointed to by variables. 2. Can be passed as arguments to procedures. 3. Can be returned as procedure values. 4. Can be included in data structures.
Example: sum-integers Signature: sum-integers(a,b) Purpose: to compute the sum of integers in the interval [a,b]. Type: [Number*Number -> Number] Post-conditions: result = a + (a+1) + ... + b. Example: (sum-integers 1 5) should produce 15 Tests: (sum-integers 2 2) expected value: 2 (sum-integers 3 1) expected value: 0 (define sum-integers (lambda (a b) (if (> a b) 0 (+ a (sum-integers (+ a 1) b)))))
Example: sum-cubes Signature: sum-cubes(a,b) Purpose: to compute the sum of cubic powers of integers in the interval [a,b]. Type: [Number*Number -> Number] Post-conditions: result = a^3 + (a+1)^3 + ... + b^3. (define sum-cubes (lambda (a b) (if (> a b) 0 (+ (cube a) (sum-cubes (+ a 1) b)))))
Example: pi-sum Signature: pi-sum(a,b) Purpose: to compute the sum 1/(a*(a+2)) + 1/((a+4)*(a+6)) + 1/((a+8)*(a+10)) + ... (which converges to PI/8, when started from a=1). Type: [Number*Number -> Number] Pre-conditions: if a < b, then a > 0. Post-conditions: result = 1/a*(a+2) + 1/(a+4)*(a+6) + ... + 1/(a+4n)*(a+4n+2), s.t. a+4n <= b, a+4(n+1) > b (define pi-sum (lambda (a b) (if (> a b) 0 (+ (/ 1 (* a (+ a 2))) (pi-sum (+ a 4) b)))))
Abstraction Signature: sum(term,a,next,b) Purpose: to compute the sum of terms, defined by <term> in predefined gaps, defined by <next>, in the interval [a,b]. Type: [[Number -> Number]*Number*[Number -> Number]*Number -> Number] Post-conditions: result = (term a) + (term (next a)) + ... (term n), where n = (next (next ...(next a))) <= b (define sum (lambda (term a next b) (if (> a b) 0 (+ (term a) (sum term (next a) next b)))))
Using the abstracted form (define sum-integers (lambda (a b) (sum (lambda (x) x) a (lambda (x) (+ x 1)) b))) (define sum-cubes (lambda (a b) (sum cube a (lambda (x) (+ x 1)) b))) (define pi-sum (lambda (a b) (sum pi-term a pi-next b))) (define pi-term (lambda (x) (/ 1 (* x (+ x 2))))) (define pi-next (lambda (x) (+ x 4)))
Advantages • Code reuse • Easier maintenance, understanding, debugging… • General interface • Expresses a well-defined concept • Allows for further abstraction (define dx 0.005) (define integral (lambda (f a b) (* (sum f (+ a (/ dx 2)) add-dx b) dx))) (define add-dx (lambda (x) (+ x dx)))
Fixed Points a x0 is a fixed point of F(x) if F(x0) = x0 x0 = Example: is a fixed point of F(x) = a/x
Finding fixed points for f(x) • Start with an arbitrary first guess x1 • Each time: • try the guess, f(x) ~ x ?? • If it’s not a good guess try the next guess xi+1 =f(xi) (define (fixed-point f first-guess) (define tolerance 0.00001) (define (close-enough? v1 v2) (< (abs (- v1 v2)) tolerance)) (define (try guess) (let ((next (f guess))) (if (close-enough? guess next) guess (try next)))) (try first-guess))
An example: f(x) = 1+1/x (define (f x) (+ 1 (/ 1 x))) (fixed-point f 1.0) X1 = 1.0 X2 = f(x1) = 2 X3 = f(x2) = 1.5 X4 = f(x3) = 1.666666666.. X5 = f(x4) = 1.6 X6 = f(x5) = 1.625 X7 = f(x6) = 1.6153846… Exact fixed-point: 1.6180339… Note how odd guesses underestimate And even guesses Overestimate.
Another example: f(x) = 2/x (define (f x) (/ 2 x)) (fixed-point f 1.0) x1 = 1.0 x2 = f(x1) = 2 x3 = f(x2) = 1 x4 = f(x3) = 2 x5 = f(x4) = 1 x6 = f(x5) = 2 x7 = f(x6) = 1 Exact fixed-point: 1.414213562…
How do we deal with oscillation? Consider f(x)=2/x. If guess is a number such that guess < sqrt(2) then 2/guess > sqrt(2) So the average of guess and 2/guess is always an even Better guess. So, we will try to find a fixed point of g(x)= (x + f(x))/2 Notice that g(x) = (x +f(x)) /2 has the same fixed points as f. For f(x)=2/x this gives: g(x)= (x + 2/x)/2
Extracting the common pattern: average-damp (define (average-damp f) (lambda (x)(average x (f x)))) average-damp: (number number) (number number) A procedure is fed as input A procedure is returned ((average-damp square) 10) ((lambda (x) (average x (square x))) 10) (average 10 (square 10)) 55
(define (sqrt x) (fixed-point (average-damp (lambda (y) (/ x y))) 1)) For the cubic root of x, fixed point of f(y) = x/y2 (define (cubert x) (fixed-point (average-damp (lambda (y) (/ x (square y)))) 1))
Further abstraction (define (osc-fixed-point f first-guess) (fixed-point (average-damp f) first-guess)) (define (sqrt x) (osc-fixed-point (lambda (y) (/ x y)) 1.0) (define (cubert x) (osc-fixed-point (lambda (y) (/ x (square y))) 1.0)
Newton’s method A solution to the equation: F(x) = 0 is a fixed point of: G(x) = x - F(x)/F’(x) (define (newton-transform f) (lambda (x) (- x (/ (f x) ((deriv f) x))))) (define (newton-method f guess) (fixed-point (newton-transform f) guess)) (define (sqrt x) (newton-method (lambda (y) (- (square y) x)) 1.0))
Further abstraction (define (fixed-point-of-transform f transform guess) (fixed-point (transform f) guess)) (define (osc-fixed-point f guess) (fixed-point-of-transform f average-damp guess)) (define (newton-method f guess) (fixed-point-of-transform f newton-transform guess))