CSC151 2007S, Class 44: Higher Order Procedures Admin: * The joy of teaching at 8:00 a.m. * Are there questions on the project? * Yes, it's due Friday. * EC for ... * Tuesday's Mental Health discussion. * Pride Week activities. * Watch Anna and not Jill ride unicycles in the Pride Parade on Saturday. * 26th at noon, from 10th and Park to 8th East * Thursday's Thursday Extra. (Dr. Davis on her graduate research.) * Some global health event this week. Figure them out. * Reading for Tuesday: Searching. (Already available.) * I'm sad that some people missed both Friday and Monday's class. Overview: * Elegance. * Procedures as parameters. * Procedures as return values. * Writing map. * Writing all?. ==Context: Design Patterns, Elegance, and More== * We care about speed. * But we are not just utilitiarian; we might also have an aesthetic [sp] of algorithms * What makes an algorithm appealing, elegant, etc? * Depends on the reader. [Sam] * No unnecessary code (if test #t #f) => test (+ foo 0) => foo * Concision * Today: * Some techniques for making code more elegant * Also work for relieving programmer work * General strategy: Take a common algorithm/procedure design strategy, and encapsulate it in a procedure (define add2togrades (lambda (grades) (if (null? grades) null (cons (+ 2 (car grades)) (add2togrades (cdr grades)))))) (define rescalegrades (lambda (grades) (if (null? grades) null (cons (/ (car grades) 2) (rescalegrades (cdr grades)))))) Ah hah! map does a better job for us (define add2togrades (lambda (grades) (map (lambda (x) (+ 2 x) grades)))) (define add2togrades (let ((add2 (lambda (x) (+ 2 x)))) (lambda (grades) (map add2 grades)))) What if Scheme didn't have map. While we would be sad (sniff), we could write ourselves. (define map (lambda (fun lst) (if (null? lst) null (cons (fun (car lst)) (map fun (cdr grades)))))) (define tally (lambda (pred? lst) (if (null? lst) 0 (if (pred? (car lst)) (+ 1 (tally pred? (cdr lst))) (tally pred? (cdr lst)))))) Lots of these kinds of procedures built in to Scheme (or to DrFu) A wider variety others write (apply fun (v1 v2 v3 ... vn)) => (fun v1 v2 v3 ... vn) (define add2togrades (lambda (grades) (map (lambda (x) (+ 2 x)) grades))) Pattern to the lambda: Filled in one argument of + * left-section implements that pattern * (left-section f v) == (lambda (x) (f v x)) * (l-s f v) == (lambda (x) (f v x)) (define add2togrades (lambda (grades) (map (left-section + 2) grades))) (define add2togrades (left-section map (left-section + 2))) (left-section f v) = (lambda (x) (f v x)) (left-section map (left-section + 2)) = (lambda (x) (map (left-section + 2) x)) (lambda (x) (map (left-section + 2) x)) = (lambda (x) (map (lambda (y) (+ 2 y)) x)) Why is (left-section map (left-section + 2)) better than (lambda (x) (map (lambda (y) (+ 2 y)) x)) ? (1) It's smaller (a) It uses fewer characters, particularly if you write (l-s map (l-s + 2)) (b) It uses fewer parens. (c) It uses fewer symbols. (2) Only experienced Scheme programmers understand it, which makes us feel superior. (3) It's close to something we'd like to write, which is "map (+ 2) onto whatever you are applied to" [Think about our original desire to write (map (+ 2) lst)]