Functional Problem Solving (CSC 151 2014F) : EBoards

CSC151.01 2014F, Class 31: Naming Local Procedures


Overview

Preliminaries

Admin

Upcoming Work

Extra Credit Opportunities

Academic

Peer Support

Questions

When is our in class written final: on December 19 at 9:00 AM or 2:00 PM?

From the course home page: "The final examination for this course is optional. It can be used as a makeup for one examination. I will count the final examination only if it is higher than your lowest examination, and it will replace the grade for that examination. Our final examination is scheduled for 9:00 a.m. on Friday, Dec. 19. However, since my other course has a final at 9:00 a.m. on Tuesday, December 16, I can also offer the final then. (If neither time works for you, let's talk. I'll find another time.)"

What is the difference between the husk and kernel?

The husk is the portion of the procedure that checks the preconditions. The kernel is the portion of the procedure that does the real work.

If there's time in class tomorrow, could you explain how the up-sum down-sum recursive procedure works?

Certainly. I've put it at the end of today's topics.

Preparation

The reading covered three main issues.

Spend two minutes talking about these issues with your partner.

An Example: Three Ways to Reverse a List

Here's the reverse procedure we've written in the past.

(define reverse1
  (lambda (lst)
    (reverse-kernel lst null)))
(define reverse-kernel
  (lambda (remaining so-far)
    (if (null? remaining)
        so-far
        (reverse-kernel (cdr remaining) (cons (car remaining) so-far)))))

Here's the same procedure, using letrec. (Why? Because I want to hide the kernel from the outside world, since no one would ever call it, and some people would call it incorrectly.)

(define reverse2
  (letrec ([kernel (lambda (remaining so-far)
                     (if (null? remaining)
                         so-far
                         (kernel (cdr remaining) 
                                 (cons (car remaining) so-far))))])
    (lambda (lst)
      (kernel lst null))))

The "define a recursive helper and then call it" pattern is very common, so Scheme includes a special syntax for it.

(define reverse3
  (lambda (lst)
   (let kernel ([remaining lst]
                [so-far null])
      (if (null? remaining)
          so-far
          (kernel (cdr remaining) 
                  (cons (car remaining) so-far))))))

Another Example: Summing Up and Down

> (letrec ([up-sum
            (lambda (ls)
              (if (null? ls)
                  0
                  (+ (car ls) (down-sum (cdr ls)))))]
           [down-sum
            (lambda (ls)
              (if (null? ls)
                  0
                  (+ (- (car ls)) (up-sum (cdr ls)))))])
    (up-sum (list 1 23 6 12 7)))

Motivation:

Stepping through the procedure:

(up-sum '(1 23 6 12 7)) (+ 1 (down-sum '(23 6 12 7))) (+ 1 (+ -23 (up-sum '(6 12 7)))) (+ 1 (+ -23 (+ 6 (down-sum '(12 7))))) (+ 1 (+ -23 (+ 6 (+ -12 (up-sum '(7)))))) (+ 1 (+ -23 (+ 6 (+ -12 (+ 7 (down-sum '())))))) (+ 1 (+ -23 (+ 6 (+ -12 (+ 7 0)))))

Remaining Questions

Don't seem to be any.

Lab

How do I check if all of the values in a list are irgb colors?

Option one: Work from the code you had yesterday.

    (define all-drawings?
      (lambda (lst)
        (or (null? lst)
            (and (drawing? (car lst))
                 (all-drawings? (cdr lst))))))

Replace drawings with irgb.

    (define all-irgb?
      (lambda (lst)
        (or (null? lst)
            (and (irgb? (car lst))
                 (all-irgb? (cdr lst))))))

Option two: Use the not-yet-documented all procedure.

The form is (all PREDICATE LST).

Example:

    > (all irgb? (list "red" 23))
    #f
    > (all irgb? (list (irgb 212 121 5) (irgb 100 100 100)))
    #t