Functional Problem Solving (CSC 151 2016S) : EBoards

CSC151.02 2016S, Class 33: Naming Local Procedures


Overview

Preliminaries

Admin

Reminders

Upcoming Work:

Extra Credit

Academic / Artistic

Peer

Miscellaneous

Regular Peer

Misc

Far in the Future

Questions

Topical Overview

We've been looking at recursion, particularly recursion over lists.

In writing recursive procedures, we often find it helpful to write recursive helper procedures.

Detour: Which is more efficient?

    (define sum
      (lambda (lst)
        (if (null? lst)
            0
            (+ (car lst) (sum (cdr lst))))))

vs.

    (define sum
      (lambda (lst)
        (sum-helper 0 lst)))

    (define sum-helper
      (lambda (so-far remaining)
        (if (null? remaining)
            so-far
            (sum-helper (+ so-far (car remaining))
                        (cdr remaining)))))

Note: Those two are more-or-less equally efficient.

If we use helper recursion, we can write

    (define irgb-brightest
      (lambda (colors)
        (irgb-brightest-helper (car colors) (cdr colors))))

    (define irgb-brighest-helper
      (lambda (so-far remaining)
        (cond
          ; We've looked at all the colors
          [(null? remaining)
           so-far]
          ; The best estimate so far is at least as bright as the
          ; next available color
          [(>= (irgb-brightness so-far) (irgb-brightness (car remaining)))
           (irgb-brightest-helper so-far (cdr remaining))]
          ]
          ; The next available color is brighter
          [else
           (irgb-brightest-helper (car remaining) (cdr remaining))]
          ])))

We also use helpers because the "table method" (see the whiteboard) can help us design and implement recursive procedures.

And it's a lot easier to print out the status of your procedure.

Our past experience tells us that helpers should be local.

We'd like to write

    (define irgb-brightest
      (let ([irgb-brighest-helper
              (lambda (so-far remaining)
                (cond
                  ; We've looked at all the colors
                  [(null? remaining)
                   so-far]
                  ; The best estimate so far is at least as bright as the
                  ; next available color
                  [(>= (irgb-brightness so-far) (irgb-brightness (car remaining)))
                   (irgb-brightest-helper so-far (cdr remaining))]
                  ]
                  ; The next available color is brighter
                  [else
                   (irgb-brightest-helper (car remaining) (cdr remaining))]
                  ])))
        (lambda (colors)
          (irgb-brightest-helper (car colors) (cdr colors)))))

Problem: let doesn't work for recursive procedures.

Solution one: Use letrec instead.

Solution two: Use something that matches our table model: named let.

    (define irgb-brightest
      (lambda (colors)
        (let irgb-brightest-helper ([so-far (car colors)] 
                     [remaining (cdr colors)])
           (cond
              ; We've looked at all the colors
              [(null? remaining)
               so-far]
              ; The best estimate so far is at least as bright as the
              ; next available color
              [(>= (irgb-brightness so-far) (irgb-brightness (car remaining)))
               (irgb-brightest-helper so-far (cdr remaining))]
              ]
              ; The next available color is brighter
              [else
               (irgb-brightest-helper (car remaining) (cdr remaining))]
          ])))

Lab

Start looking at the lab.