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.
----------------------------------------