;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; U. C. Berkeley ;; ;; EECS Computer Science Division ;; ;; CS3L Lecture 08 Answers ;; ;; (Higher-order functions) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;; ;; EVERY ;;;;;;;; (every first '(john fitzgerald kennedy)) ;; ==> (j f k) (define (square x) (* x x)) ;; ==> square (every square '(1 2 3 4)) ;; ==> (1 4 9 16) ;; Let's make all words plural (define (plural w) (word w 's)) (plural 'book) ;; ==> books (plural 'cherry) ;; ==> cherrys ;; What's wrong and how do we fix it? (define (plural w) (if (equal? (last w) 'y) (word (bl w) 'ies) (word w 's))) (plural 'book) ;; ==> books (plural 'cherry) ;; ==> cherries (every plural '(book cherry fan)) ;; ==> (books cherries fans) ;; Does this cover all cases? ;; No: hoof, deer, lass, church, etc. (every plural '(hoof deer lass church)) ;; ==> (hoofs deers lasss churchs) ;; Every also works on words, but ;; returns a sentence (which might ;; seem strange) (every square 1234) ;; ==> (1 4 9 16) (define (numberize letter) (cond ((equal? letter 'a) 4) ((equal? letter 'e) 3) ((equal? letter 'i) 1) ((equal? letter 'o) 0) ((equal? letter 'u) 7) (else letter))) (numberize 'a ) ;; ==> 4 (numberize 'z ) ;; ==> z (every numberize '(facetious)) ;; ==> (facetious) (every numberize 'facetious) ;; (f 4 c 3 t 1 0 7 s) ;; We'll soon see how to turn ;; a sentence into a word. ;; We want to be able to numberize ;; a whole sentence! ;;;;;;; ;; KEEP ;;;;;;; (keep even? '(1 3 4 7 2)) ;; ==> (4 2) (keep even? '(2 4 6)) ;; ==> (2 4 6) (keep even? '(1 3 5)) ;; ==> () (define (a-word? wd) (equal? 'a (first wd))) (keep a-word? '(ada bill cal ant)) ;; ==> (ada ant) ;; Why can't we just do this (keep (equal? 'a (first)) '(ada bill cal ant)) ;; ==> Because keep needs a function as ;; ==> its first argument, but equal ... ;; ==> returns a value. Actually, it's ;; ==> an error as written. ;; Like every, keep will accept a word as second argument. (define (vowel? letter) (member? letter '(a e i o u))) (keep vowel? '(facetious)) ;; ==> () (keep vowel? 'facetious) ;; ==> aeiou (keep vowel? 'rhythm) ;; ==> "" ;;;;;;;;;;;;; ;; ACCUMULATE ;;;;;;;;;;;;; (accumulate + '(1 2 3 4)) ;; ==> (+ 1 (+ 2 (+ 3 4))) ;; ==> 10 ;; Order of parens can be important! ;; Question: What is the following? ;; (that is, is it first-two first or last-two first?) ;; When you call a numerical function with multiple arguments, ;; It does things in a LEFT-ASSOCIATIVE way (first two first, ;; then that answer with the next one, etc. (/ 4 2 2) ;; ==> 4/2 = 2 then 2/2 = 1 ;; (/ (/ 4 2) 2) ;; But accumulate does things in a RIGHT-ASSOCIATIVE way ;; (Last two first, then the third from last with that answer, etc.) (accumulate / '(4 2 2)) ;; (/ 4 (/ 2 2)) ;; ==> 4 ;; Remember how we said we would learn ;; how to combine a sentence into a word? (accumulate word '(1 2 3 4)) ;; ==> (word 1 (word 2 (word 3 4))) ;; 1234 (accumulate word '(cal is toga)) ;; ==> calistoga (accumulate word '(f 4 c 3 t 1 0 7 s)) ;; ==> f4c3t107s ;; How do we write numberize-sent ? (define (numberize-word wd) (accumulate word (every numberize wd))) (numberize-word 'facetious) ;; ==> f4c3t107s (define (numberize-sent sent) (every numberize-word sent)) (numberize-sent '(dan is being facetious)) ;; ==> (d4n "1s" b31ng f4c3t107s) ;; The "s around 1s is fine, it's because ;; the word procedure wasn't sure if it ;; was going to be a number with leading ;; zeros, so it put ""s around it. ;; Can we write our own binary function ;; to pass to accumulate? (define (save-letters word1 word2) (if (equal? (last word1) (first word2)) (word (butlast word1) word2) (word word1 word2))) (save-letters 'cal 'bears) ;; ==> calbears (save-letters 'wheeler 'rocks) ;; ==> wheelerocks (accumulate save-letters '(one evening guido opined delightfully)) ;; ==> oneveninguidopinedelightfully ;; Accumulate on one arg doesn't even call ;; the function, it just returns ans. (define (cause-error x y) (/ 0 0)) (cause-error 4 2) ;; ==> ERROR (accumulate cause-error 'a) ;; ==> a (accumulate cause-error '(a)) ;; ==> a ;; Accumulate on zero arg returns the ;; function identity, if available. (accumulate * '()) ;; ==> 1 (accumulate max '()) ;; ==> ERROR -- Can't accumulate empty input ;; ==> with that combiner ;;;;;;;;;;;;;;; ;; WRITING HOFS ;;;;;;;;;;;;;;; ;; We can now write our very own ;; higher-order-procedures! Holy cow! ;; COUNT-IF ;; returns the count of the number of ;; words that satisfy the predicate ;; (define (count-if pred? sent) (count (keep pred? sent))) (count-if a-word? '(ada bill cal ant)) ;; ==> 2 ;; ALL? ;; ;; Returns #t if all of the elements ;; in sent satisfy predicate, otherwise ;; returns the number that don't. ;; Is this a good proposal? ;; ==> No, because a number is also true, ;; ==> since it isn't #f, so this proposal ;; ==> would always return true! ;; Howabout return #t or #f if all satisfy ;; the predicate pred? (define (all? pred? sent) (= (count sent) (count-if pred? sent))) (all? a-word? '(ada bill cal ant)) ;; ==> #f (all? a-word? '(ansel adams and alan alda)) ;; ==> #t ;;;;;;;;;;;;;;;;; ;; COMBINING HOFS ;;;;;;;;;;;;;;;;; ;; We already showed how to do this ;; when we defined "count-if" and "all?"!! ;; Here's another one that combines a lot. (define (length-of-longest-a-word sent) (accumulate max (every count (keep a-word? sent)))) (length-of-longest-a-word '(I am the biggest-word-in-the-sentence)) ;; ==> 2 ;;;;;;;;;;; ;; REPEATED ;;;;;;;;;;; ;; A function that returns a function? Huh? ;; A fish whose, um, output is another fish! (define (foo x) (cond ((= x 1) +) ((= x 2) -) ((= x 3) *))) ;; How do we call it? Howabout this: (foo 1) ;; How should we really call it? ((foo 1) 3 2) ;; ==> 5 ((foo 2) 3 2) ;; ==> 1 ((foo 3) 3 2) ;; ==> 6 ;; Repeates is another function which returns ;; another function. Now let's call it ((repeated bf 3) '(cal is number one)) ;; ==> (one) ((repeated bf 3) 'berkeley) ;; ==> keley ((repeated bf 100) 'berkeley) ;; ==> ERROR (repeated bf 3 'berkeley) ;; ERROR -- Wrong number of arguments ;; passed to procedure (define (double x) (* x 2)) ((repeated double 100) 1) ;; 2^100 = 1267650600228229401496703205376