;; The first three lines of this file were inserted by DrScheme. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-advanced-reader.ss" "lang")((modname lect03b) (read-case-sensitive #t) (teachpacks ((lib "world.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ((lib "world.ss" "teachpack" "htdp"))))) #| The design recipe: 1. Data Def'n 2. Examples of Data 3. Template for functions handling the data 4a Write function header b Write function comments c Write test cases d Write function body 5. run tests |# ; Data definition: ; A boa is: ; (make-boa name length) ; where length is in meters. (define-struct boa (name length)) ; make-boa: (-> string number boa) ; Examples of the data: (make-boa "Minime" 0.2) (make-boa "Nidhogg" 23) (define bo (make-boa "Mr. Bojangles" 3.3)) ; Creates a struct 'boa', along with: ; constructor: make-boa ; accessors: boa-name, boa-length ; predicate: boa? ; mutators: set-boa-name!, set-boa-length! [DISALLOWED for this class.] ;;; A template, for *any* function involving boas: #;(define (boa-fun a-boa) ··· (boa-name a-boa) ··· (boa-length a-boa) ··· ) ; can-fit?: (-> boa number boolean) ; Can a-boa fit in a carrier whose length is carrier-len? ; (define (can-fit? a-boa carrier-len) (<= (boa-length a-boa) carrier-len)) (check-expect (can-fit? (make-boa "Slinky" 3) 2) false) (check-expect (can-fit? (make-boa "Slinky" 3) 4) true) (check-expect (can-fit? (make-boa "Slinky" 3) 3) true) ; Data definition: ; A dillo is: ; (make-dillo [string] [number] [boolean]) ; (define-struct dillo (name length alive?)) ; Examples: (make-dillo "Phyllis" 0.3 true) (make-dillo "Pickles" 0.6 false) ;;; Template for any dillo-handling function: #;(define (fun-for-dillo d) ···(dillo-name d) ··· (dillo-length d) ··· (dillo-alive? d) ) ; hit-with-truck: (-> dillo dillo) ; (define (hit-with-truck a-dillo) (make-dillo (dillo-name a-dillo) (+ (dillo-length a-dillo) 1) false) ) (check-expect (hit-with-truck (make-dillo "Phyllis" 0.3 true)) (make-dillo "Phyllis" 1.3 false)) (check-expect (hit-with-truck (make-dillo "Pickles" 0.6 false)) (make-dillo "Pickles" 1.6 false)) ; Data definition: ; An Animal is ; - a boa, or ; - a dillo. ;;; Template for *any* animal-handling function: #;(define (animal-fun a) (cond [(boa? a) (boa-length a) ··· (boa-name a)] [(dillo? a) (dillo-length a) ··· (dillo-alive? a)··· (dillo-name a)] )) ;; Define: ; grow-animal : (-> animal num animal) ; Grow an animal by the given percentage. ; (define (grow-animal a pct) (cond [(boa? a) (make-boa (boa-name a) (* (+ 1 (/ pct 100)) (boa-length a)))] [(dillo? a) (make-dillo (dillo-name a) (* (+ 1 (/ pct 100)) (dillo-length a)) (dillo-alive? a))] )) (check-expect (grow-animal (make-boa "Minime" 0.2) 50) (make-boa "Minime" 0.3)) (check-expect (grow-animal (make-dillo "Phyllis" 0.3 true) 100) (make-dillo "Phyllis" 0.6 true)) (check-expect (grow-animal (make-dillo "Pickles" 1.6 false) 50) (make-dillo "Pickles" 2.4 false)) ; animal-length : (-> animal num) ; Return the length of any animal. (define (animal-length a) (cond [(boa? a) (boa-length a)] [(dillo? a) (dillo-length a)] )) (check-expect (animal-length (make-boa "Minime" 0.2)) 0.2) (check-expect (animal-length (make-dillo "Phyllis" 0.3 true)) 0.3) (check-expect (animal-length (make-dillo "Pickles" 1.6 false)) 1.6) ; too-long? : (-> animal boolean) ; Is an animal unsually long? ; (More than 1m for a dillo, and more than 3m for a boa.) ; (define (too-long? a) (cond [(boa? a) (> (boa-length a) 3)] [(dillo? a) (> (dillo-length a) 0.5)] )) (check-expect (too-long? (make-boa "Minime" 0.2)) false) (check-expect (too-long? (make-dillo "Phyllis" 0.3 true)) false) (check-expect (too-long? (make-dillo "Pickles" 1.6 false)) true) (check-expect (too-long? bo) true) ; List of Animals, for a zoo: ; Data definition: ; A list-of-animal is: ; - empty ; - (cons [animal] [list-of-animal]) ; Examples of the data: empty (define loa1 (cons (make-boa "Minime" 0.3) empty)) (define loa2 (cons (make-dillo "Pickles" 1.6 false) loa1)) (define loa3 (cons (make-dillo "Phyllis" 0.3 true) (cons (make-dillo "Pickles" 1.6 false) (cons (make-boa "Minime" 0.3) empty)))) ;;; TEmplate for any list-of-Animal-handling function: #;(define (fun-for-loa aloa) (cond [(empty? aloa) ...] [(cons? aloa) (first aloa) ... (fun-for-loa (rest aloa))])) ; total-len : (-> (list-of animal) num) (define (total-len aloa) (cond [(empty? aloa) 0] [(cons? aloa) (+ (animal-length (first aloa)) (total-len (rest aloa)))])) (check-expect (total-len empty) 0) (check-expect (total-len loa1) 0.3) (check-expect (total-len loa2) 1.9) (check-expect (total-len loa3) 2.2) ;; Write: ; num-too-long : (-> (list-of animal) natnum) ; Count how many animals in the list are too long. (define (num-too-long aloa) (cond [(empty? aloa) 0] [(cons? aloa) (if (too-long? (first aloa)) (+ 1 (num-too-long (rest aloa))) (+ 0 (num-too-long (rest aloa))))])) (check-expect (num-too-long empty) 0) (check-expect (num-too-long loa1) 0) (check-expect (num-too-long loa2) 1) (check-expect (num-too-long loa3) 1) (check-expect (num-too-long (cons bo loa3)) 2) ;; Write: ; collect-long-animals: (-> (list-of animal) (list-of animal)) (define (collect-long-animals aloa) (cond [(empty? aloa) empty] [(cons? aloa) (if (too-long? (first aloa)) (cons (first aloa) (collect-long-animals (rest aloa))) (collect-long-animals (rest aloa))) ])) (check-expect (collect-long-animals empty) empty) (check-expect (collect-long-animals loa1) empty) (check-expect (collect-long-animals loa2) (cons (make-dillo "Pickles" 1.6 false) empty)) (check-expect (collect-long-animals loa3) (cons (make-dillo "Pickles" 1.6 false) empty)) (check-expect (collect-long-animals (cons bo loa3)) (cons bo (cons (make-dillo "Pickles" 1.6 false) empty))) ; grow-all: (-> (list-of animal) number (list-of animal)) (define (grow-all pct aloa) (cond [(empty? aloa) empty] [(cons? aloa) (cons (grow (first aloa)) (grow-all pct (rest aloa)))])) ;; Write: ; take-one-alive : (-> (list-of dillo) (union dillo false)) (define (take-one-alive alod) (cond [(empty? alod) false] [(cons? aloa) (if (dillo-alive? (first alod)) (first alod) (take-one-alive (rest alod)))])) ; add-at-end : (-> (list-of animal) animal (list-of animal)) ; Given a list of animals and another animal, ; Return a list containing all the listed ; (define (add-at-end zoo newguy) ...) #| Compare to the data defn for natnums: ; Data def'n: ; A natnum is: ; - 0, or ; - (add1 [natnum]) What would a template look like for natnums? Did our code for ! follow the template? Yes! |# #| The robo-rally game: A simple robot game has robots follow instructions like "walk 2, turn left, walk 4, walk 6, turn right ...". We want a data definition to capture this. A list-of-num-and-sym is - empty, or - (cons number list-of-num-and-sym) - (cons symbol list-of-num-and-sym) Develop examples and template (cons 1 (cons 'left (cons 5 (cons 'right empty)))) Alternate syntax: (list 1 'left 5 'right) ;; total-steps : list-of-num-and-sym -> number ;; produces the sum of all the numbers in the list |# ;; next topic: Accumulator version ;; (How would you have written the above in Java?) ;; Just so we can compile even if we use ··· in stub functions above: (define ··· "a stub value") ;; (Note that we can't use '...'; this is reserved in Scheme to ;; indicate repetition of a macro pattern.)