CS153, Class 9: Local Bindings Overview: * Discussion of writeup 1 * Why name things? * Naming for efficiency and clarity: smallest-in-list. * Two mechanisms for naming: let and let*. * Lab Administrivia: * Probably more in the outline than I need. * Writeup 1 graded. Results emailed. To be discussed. * Questions on homework 1? * Read Preconditions and Postconditions * Did anyone come up with an appropriate iterative efficient exponentiation algorithm? * Did anyone every figure out why (length (car '('(a)))) is 2? ---------------------------------------- Questions on Homework 1 Q. What's the base case for flatten? A. flatten "unnests" sublists and sub-sublists and ... So ... to flatten the empty list, you get the empty list. Q. Should I document my "really weird" Scheme programming? A. Preferably. ---------------------------------------- Recursion vs. Iteration There are many problems (such as the exponentiation) that can be solved efficiently and cleanly recursively, but not so cleanly iteratively. The converse does not hold. Is there a fast way to compute x^n, given that you can quickly compute e^m? x = e^(log x) x^n = (e^(log x))^n = e^((log x)*n) In Scheme: (exp (* (log x) n)) ---------------------------------------- > (length (car '('(a)))) 2 'anything is shorthand for (quote anything) '(op value) ((quote a)) ---------------------------------------- Observations on writeup 1: * Here's one way to show me your testing (max 2 3 5) 5 (display '(max 2 3 5)) (max 2 3 5) (define test (lambda (exp) (display exp) (newline) (eval exp))) (test '(max 2 3 5)) (max 2 3 5) 5 Stupid picky thing: Line length. Strive for 72 ; adfasdk asdfdasf asdfsda sdfa asdf asdfasdf adsfasdf asdasdf aasd; dfas In vi, type }!fmt to rearrange a paragrph to 72 characters wide. Less picky things: Defining procedures carefully * "Takes numbers as parameters" * "For fractional portions less than 0.5, round rounds down; otherwise, round rounds up." > (round 1.5) 2.0 > (round 2.5) 2.0 * "quotient find the quotient of two integers" "Given two positive integers a and b, the quotient of a and b (written (quotient a and b)) is the largest integer q, such that b*q <= a. * "max finds the maximum" "(max v1 ... vn) returns the 'most positive' value given. "(max v1 ... vn) returns vi (in v1 .. vn) such that vi >= vj for vj from v1 to vn. * Sweet observation on max > (max 1.5 3/2) 1.5 > (max 3/2 1.5) 1.5 > (max #e1.5 3/2) 1 1/2 > (max 3/2 #e1.5) 1 1/2 > #e1.5 1 1/2 ---------------------------------------- Thinking about let. It's helpful to name things. * Clarity * Ease of development * Efficiency (define largest-in-list (lambda (ls) (cond ((null? (cdr ls)) (car ls)) ((< (car ls) (largest-in-list (cdr ls))) (car ls)) (else (largest-in-list (cdr ls)))))) What happens if the largest thing is the last thing? "largest-in-list gets called recursively twice" Suppose we have five elements in the list one comparison 2 * recurse on list of 4 elements one comparison (each) 2 * recurse on list of 3 elements Simplify 3 comparisons 4 * recursion on list of 3 elements one comparison 2 * recurse on list of 2 elements 7 comparisons 8 * recursion on list of 2 elements one comparison each 2 * recurse on list of 1 elements 15 comparisons 16 * recursion on list of 1 element one comparison each, no recursion ~31 comparisons for five element list For a six element list, we'd do about 63 comparisons! Approximately 2^n comparisons for a list of length n Vs. n comparisons, in a more sensible algorithm Naming will help us (define largest-in-list (lambda (ls) (if (null? (cdr ls)) (car ls) (; Name (largest-in-list (cdr ls)) as "foo" (if ((< car ls) foo) (car ls) foo))))) In Scheme (let ((name val)) exp) (define largest-in-list (lambda (ls) (if (null? (cdr ls)) (car ls) (let ((largest-remaining (largest-in-list (cdr ls)))) (if ((< car ls) largest-remaining) (car ls) largest-remaining))))) Q: What if I need to have multiple expressions for the true part or false part of an if? A: Use (begin exp1 exp2 ... expn) Q: Use (eq? (length ls) 1) vs. (null? (cdr ls)) A. It takes n steps to find the length of a list of length n. Use the null? test. ----------------------------------------