6.001 Recitation #7 – Feb 26, 2003

 

RI: Konrad Tollmar

 

• Programming practice

1. Prog practice

  1. Layout
  2. Documenting
  3. Debug
  4. Test case
  5. Types (number?, string?, Boolean?, List?, Pair? )

 

2. Errors

Common Sources of (Scheme) Errors

• Typographical errors (misspellings)

• Syntax errors (parens)

• Errors inside a module (procedure or algorithm)

• Errors connecting modules together (program structure)

 

Scheme Error Messages

• Unbound or unassigned variable

Either a typographical error, or use of a variable outside of the part of the program in which it is available (e.g. using a

variable created by let outside the body of the let, or use of a variable created by define within a procedure outside of

that procedure).

• Applying something that isn't a procedure

"The object ... is not applicable" The value of the first subexpression in a combination must be a procedure.

• Wrong number of arguments to a procedure The number of arguments in a call to a procedure must

match the number of parameters the procedure expects.

• Wrong type or range of arguments to a primitive procedure

Some primitive procedures require a specific type of argument.

• Numerical errors (overflow, underflow, divide by zero)

The numerical procedures can fail in a number of ways when dealing with inexact numbers that are either very large, very small, or very close to zero.

• Other errors

A number of the procedures built into MIT Scheme can detect special errors and report them. For example, "Unable to open file ... because: no such file or directory."

 

MIT Scheme Debugging Tools

• Pretty printer

• Debugger

• Tracing

• Breakpoints

 

Debugging Strategy

• Don't throw away your state when an error occurs

• Think abstractly to locate a module that is failing

• Examine only modules that fail

• Errors are more common in connecting modules together than in individual modules

 


3. Let

 

Use let to write a procedure that compute

a = 1 + xy; b = 1 - y; f(x,y) = a2x + by + ab

 

 

(define (f x y)

 (define (f-helper a b)

  (+ (* x (square a))

   (* y b)

   (* a b)))

 (f-helper (+ 1 (* x y))

           (- 1 y)))

 

(define (f x y)

 ((lambda (a b)

   (+ (* x (square a))

      (* y b)

      (* a b)))

   (+ 1 (* x y))

        (- 1 y)))

 

(define (f x y)

 (let ((a (+ 1 (* x y))

       (b (- 1 y)) )

      (+ (* x (square a))

         (* y b)

         (* a b))))

 

Let* evaluates and binds each name/value pair in

sequence, so that each definition is available to the next

 

(let* ((x 1)

       (y 2)

       (z (+ x y))

        z)

=== 3!

 

4. Eval some list procedures.

x => (())

y => (1 2 3)

z => (1 (2 3) ((4)))

w => (1 2 3 4 5)

 

(define (filter pred lst)

 (cond ((null? lst) nil)

        ((pred (car lst))

          (cons (car lst) (filter pred (cdr lst))))

        (else (filter pred (cdr lst)))))

 

(define (accumulate op init lst)

 (if (null? lst)

  init

  (op (car lst)

      (accumulate op init (cdr lst)))))

 

 

(map (lambda (x) (cons x nil)) y) -> ((1) (2) (3))

(map inc w) -> (2 3 4 5 6)

(filter odd? w) -> (1 3 5)

(map inc (filter odd? w)) -> (2 4 6)

(filter odd? (map inc w)) -> (3 5)

(accumulate + 0 (map inc (filter odd? w))) -> 12

 

5. What are the types of these procedures?

 

1. length List<A>->number

2. list-ref List<A>,number->A

3. map (A->B),List<A>->List<B>

4. filter (A->boolean),List<A>->List<A>

5. accumulate (A,B->B),B,List<A>->B

 

 

5b. Trees

 

Type Definition:

• Tree<C> = List<Tree<C>> | Leaf<C>

• Leaf<C> = C

Operations:

• leaf?

• countleaves, scaletree, enum-leaves, map-tree & tree-ref

 

Flatten tree to list of leaves:

(enumerate-leaves (list 1 (list 3 4 5)(list 2 30)))

==> (1 3 4 5 2 30)

 

(define (e-l x)

 (cond ((null? x) nil)

        ((not (pair? x)) (list x))

        (else (append (e-l (car x))

                      (e-l (cdr x))))))

6. More higher-order procedures.

(define comp

 

(lambda (a b)

        

  (lambda (x)

   (if x a b)))

)