320 likes | 346 Views
Learn about Design By Contract principles and Recursive Procedures in programming languages. Understand the concept of Iteration vs. Recursion, Scope and Binding, and High-order Procedures.
E N D
Principles Of Programming Languages Lecture 2
Outline • Design-By-Contract • Iteration vs. Recursion • Scope and binding • High-order procedures
Design By Contract • Signature: Name of procedure and arguments • Purpose: Short text explaining what the procedure does • Type • Examples of usage • Tests indicating correctness • Preconditions: Impose a certain obligation to be guaranteed on entry by any client module that calls it • Postcondition: Guarantee a certain property on exit
Example Signature: area-of-square(length) Purpose: to compute the area of a rectangle whose side length is ‘length’ Type: [Number -> Number] Example: (area-of-square 5) should produce 25 Pre-conditions: length>= 0 Post-condition: result = length^2 Tests: (area-of-square 2) expected value: 4 (area-of-square -2) expected value: ??? [What do you think?]
Design-By-Contract in this course • You are required to write this for every procedure that you write in an exercise • In the example shown in class we will often omit it
Recursive Procedures • How to create a process of unbounded length? • Needed to solve more complicated problems. • No “for” or “while” loop constructs in scheme! • Answer: Recursion!!! • Start with a simple example.
S(n-1) • Notice that: • S(n) = S(n-1) + n2 • S(0) = 0 • These two properties completely define the function Example: Sum of squares S(n) = 02 + 12 + 22 ………. …… (n-1)2 + n2 Wishful thinking: if I could only solve the smaller instance … מבוא מורחב - שיעור 2
An algorithm for computing sum of squares (define sum-squares (lambda (n) (if (= n 0) 0 (+ (sum-squares (- n 1)) (square n)))) מבוא מורחב - שיעור 2
Evaluating (sum-squares 3) (define (sum-squares n) (if (= n 0) 0 (+ (sum-squares (- n 1)) (square n)))) (sum-squares 3) (if (= 3 0) 0 (+ (sum-squares (- 3 1)) (square 3))) (+ (sum-squares (- 3 1)) (square 3)) (+ (sum-squares (- 3 1)) (* 3 3)) (+ (sum-squares(- 3 1)) 9) (+ (sum-squares 2) 9) (+ (if (= 2 0) 0 (+ (sum-squares (- 2 1)) (square 2))) 9) … (+ (+ (sum-squares 1) 4) 9) … (+ (+ (+ (sum-squares 0) 1) 4) 9) (+ (+ (+ (if (= 0 0) 0 (+ (sum-squares (- 0 1)) (square 0))) 1) 4) 9) (+ (+ (+ 0 1) 4) 9) … 14 What would have happened if ‘if’ was a function ? מבוא מורחב - שיעור 2
Evaluating (sum-squares 3) with IF as regular form (define (sum-squares n) (if (= n 0) 0 (+ (sum-squares (- n 1)) (square n)))) (sum-squares 3) (if (= 3 0) 0 (+ (sum-squares (- 3 1)) (square 3))) (if #f 0 (+ (sum-squares 2) 9)) (if #f 0 (+ (if #f 0 (+(sum-squares 1)4)) 9)) (if #f 0 (+ (if #f 0 (+(if #f 0 (+(sum-squares 0)1))4)) 9)) (if #f 0 (+ (if #f 0 (+(if #f 0 (+(if #t 0 (+(sum-squares -1)0))1))4)) 9)) .. We evaluate all operands. We always call (sum-squares) again. We get an infinite loop…….. OOPS מבוא מורחב - שיעור 2
General form of recursive algorithms • test, base case, recursive case (define sum-sq(lambda (n) (if (= n 0) ; test for base case 0 ; base case (+ (sum-sq (- n 1)) (square n)) ; recursive case ))) • base case: small (non-decomposable) problem • recursive case: larger (decomposable) problem • at least one base case, and at least one recursive case.
Another example of a recursive algorithm • even? (define even? (lambda (n) (not (even? (- n 1))) ; recursive case ))) • (if (= n 0) ; test for base case • #t ; base case מבוא מורחב - שיעור 2
Short summary • Design a recursive algorithm by 1. Solving big instances using the solution to smaller instances. 2. Solving directly the base cases. • Recursive algorithms have 1. test 2. recursive case(s) 3. base case(s) מבוא מורחב - שיעור 2
Iteration Vs. Recursion • In scheme there is no “while” or “for” construct • Requires getting use to “wishful thinking” • Sometimes more natural! • Problem: Recursive processes are “costly’ memory-wise • Need to “remember” pending operations • Enter Iterative processes • Lots of examples to follow
Compute ab (Recursive Approach) • wishful thinking : • base case: ab=a * a(b-1) a0 = 1 • (define exp-1 • (lambda (a b) • (if (= b 0) • 1 • (* a (exp-1 a (- b 1)))))) מבוא מורחב
ab=a * a * a*…*a • Which is: b ab = a2 *a*…*a= a3 *…*a • Operationally: • Halting condition: product product * a counter counter - 1 counter = 0 Compute ab (Iterative Approach) • Another approach: מבוא מורחב
Syntactic Recursion Compute ab (Iterative Approach) (define (exp-2 a b) (define (exp-iter a counter product) (if (= counter 0) product (exp-iter a (- counter 1) (* a product))) (exp-iter a b 1)) How then, do the two procedures differ? They give rise to different processes – lets use our model to understand how.
Recursive Process • (define exp-1 • (lambda (a b) • (if (= b 0) • 1 • (* a (exp-1 a (- b 1)))))) • (exp-1 3 4) • (* 3 (exp-1 3 3)) • (* 3 (* 3 (exp-1 3 2))) • (* 3 (* 3 (* 3 (exp-1 3 1)))) • (* 3 (* 3 (* 3 (* 3 (exp-1 3 0))))) • (* 3 (* 3 (* 3 (* 3 1)))) • (* 3 (* 3 (* 3 3))) • (* 3 (* 3 9)) • (* 3 27) • 81 מבוא מורחב
Iterative Process (define (exp-2 a b) (define (exp-iter a counter product) (if (= counter 0) product (exp-iter a (- counter 1) (* a product))) (exp-iter a b 1)) (exp-2 3 4) (exp-iter 3 4 1) (exp-iter 3 3 3) (exp-iter 3 2 9) (exp-iter 3 1 27) (exp-iter 3 0 81) 81 מבוא מורחב
(exp-1 3 4) • (* 3 (exp-1 3 3)) • (* 3 (* 3 (exp-1 3 2))) • (* 3 (* 3 (* 3 (exp-1 3 1)))) • (* 3 (* 3 (* 3 (* 3 (exp-1 3 0))))) • (* 3 (* 3 (* 3 (* 3 1)))) • (* 3 (* 3 (* 3 3))) • (* 3 (* 3 9)) • (* 3 27) • 81 (exp-2 3 4) Growing amount of space (exp-iter 3 4 1) (exp-iter 3 3 3) (exp-iter 3 2 9) Constant amount of space (exp-iter 3 1 27) (exp-iter 3 0 81) 81 The Difference מבוא מורחב
operation pending no pending operations Why More Space? • Recursive exponentiation: (define exp-1 (lambda (a b) (if (= b 0) 1 (* a (exp-1 a (- b 1))))) • Iterative exponentiation: • (define (exp-2 a b) • (define (exp-iter a counter product) • (if (= counter 0) • product • (exp-iter a (- counter 1) (* a product)))) • (exp-iter a b 1))
Example: Factorial wishful thinking : base case: n! =n * (n-1)! n = 1 (define fact (lambda (n) (if (= n 1) 1 (* n (fact (- n 1)))))) Iterative or Recursive? 22
X = 2 G = 1 X/G = 2 G = ½ (1+ 2) = 1.5 X/G = 4/3 G = ½ (3/2 + 4/3) = 17/12 = 1.416666 X/G = 24/17 G = ½ (17/12 + 24/17) = 577/408 = 1.4142156 Computing SQRT: A Numeric Algorithm • To find an approximation of square root of x, use the following recipe: • Make a guess G • Improve the guess by averaging G and x/G • Keep improving the guess until it is good enough
(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))
Towers of Hanoi • Three posts, and a set of disks of different sizes. • A disk can be placed only on a larger disk (or on bottom). • At the beginning all the disks are on the left post. The goal is to move the disks one at a time, while preserving these conditions, until the entire stack has moved from the left post to another You are allowed to move only the topmost disk at a step מבוא מורחב - שיעור 4
Use our paradigm • Wishful thinking: • Smaller problem: A problem with one disk less • How do we use it ? To move n disks from post A to post C (using B as aux): Move top n-1 disks from post A to post B (using C as aux) Move the largest disk from post A to post C Move n-1 disks from post B to post C (using A as aux) We solve 2 smaller problems ! מבוא מורחב - שיעור 4
Towers of Hanoi (define (move-tower size from to aux) (cond ((= size 1) (one-move from to)) (else (move-tower (- size 1) from aux to) (one-move from to) (move-tower (- size 1) aux to from)))) (define (one-move from to) (display "Move top disk from ") (display from) (display " To ") (display to) (newline)) מבוא מורחב - שיעור 4
(mt 2 1 3 2) (mt 2 3 2 1) (mt 1 1 2 3) (mt 1 1 2 3) (mt 1 2 3 1) (mt 1 3 1 2) (one-move 1 2) (one-move 1 3) (one-move 3 2) (one-move 1 2) (one-move 2 3) (one-move 3 1) (one-move 1 2) Tree Recursion (mt 3 1 2 3) מבוא מורחב - שיעור 4
(move-tower 2 1 3 2) 3 2 1 3 2 1 3 2 1 (move-tower 2 3 2 1) 3 2 1 3 2 1 3 2 1 3 a 2 1 3 2 1 Towers of Hanoi -- trace (move-tower 3 1 2 3) Move top disk from 1 to 2 Move top disk from 1 to 3 Move top disk from 2 to 3 Move top disk from 1 to 2 Move top disk from 3 to 1 Move top disk from 3 to 2 Move top disk from 1 to 2 מבוא מורחב - שיעור 4
Time Complexity for towers of Hanoi Denote by T(n) the number of steps that we need to take to solve the case for n disks. T(n) = 2T(n-1) + 1 T(1) = 1 This solves to: T(n) = 2n-1= Q (2n) What does that mean ?
Hanoi Towers Say we want to solve the problem for 400 disks. Say it takes a second to move a disk . We need about 2400 seconds. That’s about 2373 years. That’s about 2363 millenniums. Might be longer then the age of the universe …. Infeasible !!!!
Let’s buy a fast computerand make it feasible. Our new computer can move giga billion (260 ) disks a second. Absolutely the last word in the field of computing. We need about 2340 seconds. That’s about 2313 years. That’s about 2303 millenniums. Does not help much. Infeasible !!!!