;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname 2015-10-19-lerner) (read-case-sensitive #t) (teachpacks ((lib "image.rkt" "teachpack" "2htdp") (lib "universe.rkt" "teachpack" "2htdp") (lib "batch-io.rkt" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "image.rkt" "teachpack" "2htdp") (lib "universe.rkt" "teachpack" "2htdp") (lib "batch-io.rkt" "teachpack" "2htdp")) #f))) (require 2htdp/image) ;; A Zoo is a (Listof Animals) ;; An Animal is a symbol ;; find-cat? : Zoo -> Boolean (define (find-cat.v1? zoo) (cond [(empty? zoo) false] [(cons? zoo) (or (symbol=? (first zoo) 'cat) (find-cat.v1? (rest zoo)))])) (check-expect (find-cat.v1? (list 'dog 'fish 'zebra)) false) (check-expect (find-cat.v1? (list 'dog 'fish 'cat 'zebra)) true) (check-expect (find-cat.v1? (list)) false) ;; find-dog? : Zoo -> Boolean (define (find-dog.v1? zoo) (cond [(empty? zoo) false] [(cons? zoo) (or (symbol=? (first zoo) 'dog) (find-dog.v1? (rest zoo)))])) (check-expect (find-dog.v1? (list 'dog 'fish 'zebra)) true) (check-expect (find-dog.v1? (list 'fish 'cat 'zebra)) false) (check-expect (find-dog.v1? (list)) false) ;; Generalize the two functions above: everything is the same except the particular ;; animal being looked for... ;; find-animal? : Zoo Animal -> Boolean (define (find-animal? zoo animal) (cond [(empty? zoo) false] [(cons? zoo) (or (symbol=? (first zoo) animal) (find-animal? (rest zoo) animal))])) ;; Redefine our old specific functions in terms of the general one: ;; find-dog? : Zoo -> Boolean (define (find-dog.v2? zoo) (find-animal? zoo 'dog)) ;; find-cat? : Zoo -> Boolean (define (find-cat.v2? zoo) (find-animal? zoo 'cat)) ;; Confirm that the revised versions work identically to the originals (check-expect (find-dog.v2? (list 'cat 'dog 'zebra)) (find-dog.v1? (list 'cat 'dog 'zebra))) (check-expect (find-cat.v2? (list 'cat 'dog 'zebra)) (find-cat.v1? (list 'cat 'dog 'zebra))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; add-all-numbers : LoN -> Number (define (add-all-numbers lon) (cond [(empty? lon) 0] [(cons? lon) (+ (first lon) (add-all-numbers (rest lon)))])) (check-expect (add-all-numbers (list 8 6 7 5 3 0 9)) 38) (check-expect (add-all-numbers (list) 0)) ;; mult-all-numbers : LoN -> Number (define (mult-all-numbers lon) (cond [(empty? lon) 1] [(cons? lon) (* (first lon) (mult-all-numbers (rest lon)))])) (check-expect (mult-all-numbers (list 6 5 4 3 2 1)) 720) (check-expect (mult-all-numbers (list) 1)) ;; Can we generalize the previous two functions? ;; Everything is the same, except what we return in the base case, and ;; the operation being performed! ;; Combines all the numbers in the list, starting from the given base value, using the given operation ;; process : [Listof Number] Number (Number Number -> Number) -> Number (define (process lox base op) (cond [(empty? lox) base] [(cons? lox) (op (first lox) (process (rest lox) base op))])) ;; Redefine add-all-numbers and mult-all-numbers in terms of our generalization (define (sum lon) (process lon 0 +)) (define (prod lon) (process lon 1 *)) ;; In fact, process has a far more general type: ;; process : [Listof X] Y (X Y -> Y) -> Y ;; EXERCISE: WHY does it have this type? ;; twice : Number -> Number (define (twice x) (* 2 x)) (define (triple x) (* 3 x)) ;; double-all : LoN -> LoN (define (double-all lon) (cond [(empty? lon) empty] [(cons? lon) (cons (* 2 (first lon)) (double-all (rest lon)))])) ;; triple-all : LoN -> LoN (define (triple-all lon) (cond [(empty? lon) empty] [(cons? lon) (cons (* 3 (first lon)) (triple-all (rest lon)))])) ;; add-5-to-all : LoN -> LoN (define (add-5-to-all lon) (cond [(empty? lon) empty] [(cons? lon) (cons (+ 5 (first lon)) (add-5-to-all (rest lon)))])) ;; Converts all the numbers in the list to strings ;; lon->los : LoN -> LoS (define (lon->los lon) (cond [(empty? lon) empty] [(cons? lon) (cons (number->string (first lon)) (lon->los (rest lon)))])) ;; Can we generalize the four functions above? They're entirely the same ;; except for what operation we perform on each item ;; process-all : LoN (Number -> X) -> [Listof X] ;; process-all : ([Listof X] (X -> Y) -> [Listof Y]) (define (process-all lox op) (cond [(empty? lox) empty] [(cons? lox) (cons (op (first lox)) (process-all (rest lox) op))])) (define (double-all.v2 lon) (process-all lon twice)) (define (triple-all.v2 lon) (process-all lon triple)) (define (add-5 n) (+ n 5)) (define (add-5-to-all.v2 lon) (process-all lon add-5)) (define (lon->los.v2 lon) (process-all lon number->string)) ;; do-to-5 : (Number -> X) -> X (define (do-to-5 op) (op 5)) (check-expect (do-to-5 twice) 10) (check-expect (do-to-5 number->string) "5") ;; NOTE: we don't need this in ISL+λ ;; do-op : (X -> Y) X -> Y (define (do-op op arg) (op arg)) ;; Takes a list of functions, and applies them successively to the base value ;; do-all-to-base : [Listof (X -> X)] X -> X (define (do-all-to-base lof base) (cond [(empty? lof) base] [(cons? lof) (do-op (first lof) (do-all-to-base (rest lof) base)) ])) (check-expect (do-all-to-base (list add-5 twice triple) 5) (add-5 (twice (triple 5)))) (define-struct pair (x y)) ;; A [Pair X Y] is a (make-pair X Y) ;; What is a [Pair Boolean Number]? ;; --- a (make-pair Boolean Number) ;; Give me an example of a [Pair String Symbol] ;; --- (make-pair "hi" 'anything) ;; What is (in full form) the definition of [Listof [Listof Number]]? ;; One of: ;; - empty ;; - (cons [Listof Number] [Listof [Listof Number]]) ;; where a [Listof Number] is one of ;; - empty ;; - (cons Number [Listof Number]) (define (red-circle r) (circle r 'solid 'red)) (process (process-all (list 5 10 15 20) red-circle) (square 20 'solid 'blue) beside) (process (process-all (list 15 15 15 15) red-circle) (square 0 'solid 'blue) above)