95.501 2000

 3  Building Abstractions with Procedures


What's in This Set of Notes ?


3.1 Conditional Expressions and Predicates

(cond   ( <p1> <e1>)
            ( <p2> <e2>)
            ...
            ( <pn> <en>))
(define (abs x)
    (cond    (( > x 0) x)
                (( = x 0) 0)
                ((< x 0) (- x))))

(define (abs x)
        (if (< x 0)
            (- x)
            x))

(and <e1> ...  <en>)  evaluate left to right, as soon as one expression is false return false

(or <e1> ...  <en>) evaluate left to right, as soon as one expression is true return true

(not <e>)

(define (>= x y)
     (or ( > x y) (= x y))

(define (>= x y)
    (not (< x y))


Example: Compute Square Roots using Newton's method of successive approximations

  1. guess y for value of square root of number x
  2. to get a better guess average y with x/y
For square root of 2
Guess (y) Quotient (x/y) Average ((x/y) + y) / 2 => gives next guess
1 2/1 = 2 (2 + 1)/2 = 1.5
1.5 2/1.5= 1.333 (1.3333 + 1.5) / 2 = 1.4167
1.4167 2/1.4167= 1.4118 (1.4167 + 1.4118) / 2 = 1.4142
1.4142 ... ...
  • Sqrt is first example of process defined by a set of mutually defined procedures
  • Problem breaks up naturally into subproblems: decomposition strategy
  • Details of how sqrt is computed can be hidden (black box) creating a so-called procedural abstraction
  • Take the procedure square, we know what we want, but how does it do it?
  • A procedure definition should be able to supress details
  • Users of procedure may not have written it
  • Users should not need to know how a procedure is implemented in order to use it!

  • Local names




    3.2 Procedures and the Processes They Generated


    Factorial function

     
    n! = n * (n - 1) * (n - 2) . . . 3 * 2 * 1
    n! = n * (n - 1)!


    Linear Recursive Process

    (define (factorial n)
        (if ( = n 1)
            1
            (* n (factorial ( - n 1)))))

    Substitution Model for (factorial 5)

  • This is a linear recursive process

  • Linear Iterative Process

    (define (factorial n)
        (factorial-iteration 1 1 n))

    (define (factorial-iteration product counter maximum)
        (if (> counter maximum)
            product
            (factorial-iteration (* counter product) (+ counter 1) maximum)))

    Substitution Model for (factorial 5)

  • This is a linear iterative process

  • Comment



    3.3 Other Forms of Recursion

    Tree Recursion

    Fibonacci Numbers

    Fib(n) = 0                                        if n = 0
    Fib(n) = 1                                        if n = 1
    Fib(n) = Fib(n - 1) + Fib(n - 2)        otherwise

    0, 1, 1, 2, 3, 5, 8, 13, 21 ....


    Recursive Process

    (define (fib n)
        (cond (( = n 0) 0)
                    (( = n 1) 1)
                    (else
                        (+ (fib (- n 1))
                            (fib ( - n 2))))))

  • process looks like a tree
  • inefficient due to duplicate computation

  •  


    Iterative Process

    (define (fib n)
        (fib-iteration 1 0 n))

    (define (fib-iteration a b count)
        (if (= count 0)
                b
                (fib-iteration ( + a b) a (- count 1))))

    (fib 4)
    (fib-iteration 1 0 4)
    (fib-iteration 1 1 3)
    (fib-iteration 2 1  2)
    (fib-iteration 3 2  3)
    (fib-iteration 5 3  0)
    3


    3.4 Procedures


    Procedures as Arguments

    (define (sum-int a b)
        (if (> a b)
            0
            (+     a
                    (sum-int (+ a 1) b))))
    (define (cube x) (* x x x ))

    (define (sum-cubes a b)
            (if ( > a b)
                0
                (+ (cube a)
                    (sum-cubes (+ a 1) b))))
     

  • Compute (1/(1 * 3)) + (1/(5 * 7)) + (1/(9 * 11)) + . . .   converges to pi/8

  •  

     
     
     
     
     
     
     
     
     

    (define (pi-sum  a b)
            (if ( > a b)
                0
                (+  (/ 1.0 (* a (+ a 2))
                        (pi-sum (+ a 4) b))))

    (define (inc n) (+ n 1))
    (define (identity n) n)

    (define (sum-int a b)
        (sum identity a inc b))

    (define (sum-cubes a b)
        (sum cube a inc b))

    (define (pi-sum a b)
        (define (pi-term x) (/ 1.0 (* x (+ x 2))))
        (define (pi-next x) ( + x 4))
        (sum pi-term a pi-next b))
     


    Special form Lambda

    (lambda (<formal parameters>) <body>)
     

    (lambda (x) (+ x 4)) returns a  procedure that increments x by 4 like pi-next
    (lambda (x) (/ 1.0 (* x (+ x 2)))) returns a  procedure that is like pi-term
     

    (define (plus4 x) (+ x 4)) is equivalent to (define plus4 (lambda (x) (+ x 4)))

    Note: Evaluating a lambda expression returns a procedure object

    Therefore:
     

    ((lambda (x) (+ 1 x)) 2) => 3
    in the same way:
    (define (increment x)
            (+ 1 x))
    (increment 2) => 3
    or
    (define increment (lambda (x) (+ 1 x)))
    (increment 2) => 3


    Using Lambda to create local variables

    Suppose
     
    f(x,y) = x(1 + xy)(1 + xy) + y(1 -y) + (1 + xy)(1 -y)

    if a = 1 + xy and b= 1-y

    f(x,y) = xaa + yb + ab

    Let's write the function f in scheme
    (define (f x y)
        (define (f-helper a b)
            (+     (* x (square a))
                    (* y b)
                    (* a b)))
        (f-helper (+ 1 (* x  y))
                        (- 1  y)))
    We could use lambda instead creating two variables a b that get bound to (+ 1 (* x  y)) and (- 1  y)) respectively
     
    (define (f x y)
        ((lambda a b)
                (+     (* x (square a))
                        (* y b)
                        (* a b)))
            (+ 1 (* x  y))
            (- 1  y)))


    Special form Let: Syntactic sugar for Using Lambda to Create Local Variables


    The syntax for lambda
     

    ((lambda (<var1> ...<varn>)
        <body>)
    <exp1>
    <exp2>
    .
    .
    .
    <expn>)
    can be expressed using the special form let
     
    (let ((<var1> <exp1>)
            (<var2> <exp2>)
            .
            .
            .
            (<varn> <expn>))
        <body>)
    which can be thought of as
    let <var1> have the value <exp1> and
        <var2> have the value <exp2> and
        .
        .
        .
        <varn> have the value <expn> and
    in <body>
    Therefore
    (let ((x 3)
            (y (+ x 3)))
        (* x y))

    => with generate the value 12 when evaluated


    Note: Scope of variables is in let expression
    Therefore:
     

    (define x 5)
    (+     (let (( x 3))
                (+ x (* x 10)))
            x)

    => 38

    Back to our Example


    Quiz

    Suppose you have the following function f


    Procedures as Return Values

    Average-damp is a procedure that takes as it argument a procedure that returns as its value a procedure

    (define (average-damp f)
        (lambda (x) (average x (f x))))

    Applying average-damp to the square procedure returns a procedure whose value when evaluated is the average of x and x squared

    ((average-damp square) 10) => 55



    3.5 Summary