CSC151 2009F, Class 30: Preconditions, Revisited Admin: * Welcome back from break! I hope you are feeling refreshed. * Reading for tomorrow: Local Procedure Bindings and Recursion. * The reading for today accidentally included some notes on an image model (spots) that we have not covered this semester. * I apologize. * That issue has been addressed. * We'll go over the key issues in the reading. * The distribution on the last quiz was bimodal, so we'll go over it a bit. Overview: * Notes on the quiz. * Verifying preconditions. * The error procedure. * Husk and Kernel programming. QUIZ STUFF (define rgb-dark? (lambda (rgb) (> 192 (+ (rgb-red rgb) (rgb-green rgb) (rgb-blue rgb))))) (define tally-darks (lambda (colors) (tally-darks-helper 0 colors))) (define tally-darks-helper (lambda (tally remaining-colors) (write (list 'tally-darks-helper tally remaining-colors)) (newline) (if (null? remaining-colors) tally (if (rgb-dark? (car remaining-colors)) (tally-darks-helper (+ 1 tally) (cdr remaining-colors)) (tally-darks-helper tally (cdr remaining-colors)))))) Let's document tally-darks ;;; Procedure: ;;; tally-darks ;;; Parameters: ;;; colors, a list of colors ;;; Purpose: ;;; Count the number of colors in the list that rgb-dark? considers ;;; dark. ;;; Produces: ;;; tally, an integer ;;; Preconditions: ;;; colors should include only RGB colors. ;;; rgb-dark? needs to be defined ;;; Postconditions: ;;; 0 <= tally <= (length colors) An important question for the designer of procedures: What should the procedure do when the client fails to meet the preconditions? * Don't worry about it, let the program crash or return awkward results or ... * Sam thinks this is dangerous * It might still return something, and the client won't notice that what it got back is wrong. * It can interepret numbers as RGB colors. * In a lot of procedures that have the form (if (null? (cdr lst)) (car lst) ...) * Report an error message (define rgb-reddest (lambda (colors) (if (null? (cdr colors)) (car colors) (let ((reddest-remaining (rgb-reddest (cdr colors)))) (if (> (rgb-red (car colors)) (rgb-red reddest-remaining)) (car colors) reddest-remaining))))) > (rgb-reddest (list "Grinnell")) "Grinnell" Um ... that's not quite the answer we expect, since "Grinnell" is not an RGB color. The solution? Use the error procedure. (define rgb-reddest (lambda (colors) (when (not (rgb? (car colors))) (error "You idiot, that's not an RGB color. I refuse to answer your question. You gave me the strange value" (car colors))) (if (null? (cdr colors)) (car colors) (let ((reddest-remaining (rgb-reddest (cdr colors)))) (if (> (rgb-red (car colors)) (rgb-red reddest-remaining)) (car colors) reddest-remaining))))) [Not covered in class: What happens with the empty list? Another incomprehensible error. We can fix that, too. (when (null? colors) (error "What part of NON-EMPTY LIST did you not understand?"))