CSC151 2007S, Class 34: Naming Local Procedures Admin: * Exam 2 is now ready. * We'll do a quick overview in class today. * Bring questions on Monday (and Tuesday and ...) * Please read Characters and Strings for Monday. Overview: * Husk and Kernel, revisited. * Why have local procedures. * Creating local procedures. * An example: remove-color * Lab /Husk and Kernel Programming/ * A programming technique most commonly used for verifying preconditions of a recursive procedure * Idea: You don't want to check preconditions at every recursive call. Rather, do it once and then get on with the work. * We separate the procedure into two parts * The husk checks the preconditions * The kernel does the work * Programming convention: Call the kernel "kernel" or "PROC-kernel" Example: Start with a procedure with no precondition checking (an unprotected colonel) and add rpecondition checking Problem: Given a list of colors and a color and removes all colors "near" that color. [See inserted code] (define rgb.close? (lambda (color1 color2) (and (>= 16 (abs (- (rgb.red color1) (rgb.red color2)))) (>= 16 (abs (- (rgb.green color1) (rgb.green color2)))) (>= 16 (abs (- (rgb.blue color1) (rgb.blue color2))))))) (define colors.remove-close (lambda (colors color) (letrec ((kernel (lambda (colors color) ; I need a base case! (if (null? colors) null ; Check if the car is close (if (rgb.close? (car colors) color) (kernel (cdr colors) color) (cons (car colors) (kernel (cdr colors) color))))))) ; CHECK PRECONDITIONS (cond ; (1) Make sure that colors is a list ((not (list? colors)) (throw "colors.remove-close: parameter is not a list: " colors)) ; (2) Make sure that each element in the list is an RGB color ((not (all-rgb? colors)) (throw "colors.remove-close: at least one elemento f the list is not a color")) ; (3) Make sure that color is a color ((not (rgb? color)) (throw "colors.remove-close: parameter is not an RGB color: " color)) ; IF ALL THE PRECONDITIONS SUCCEED, RUN THE KERNEL (else (kernel colors color)))))) (define colors (list (rgb.new 255 0 0) (rgb.new 250 10 10) (rgb.new 245 10 10) (rgb.new 128 10 10) (rgb.new 0 255 255) (rgb.new 0 255 0) (rgb.new 255 255 255) (rgb.new 255 15 0) )) (define all-rgb? (lambda (lst) (or (null? lst) (and (rgb? (car lst)) (all-rgb? (cdr lst)))))) Problem: Can we stop the client from even calling the kernel? Answer: Using letrec (letrec ((proc defn) (proc defn) ...) body)