;; 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.)