;; 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-beginner-reader.ss" "lang")((modname lect02b) (read-case-sensitive #t) (teachpacks ((lib "world.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "world.ss" "teachpack" "htdp"))))) ; Good program design has one function call other ; simpler ones (like `area-of-straw` and `area-of-washer`): ; (define (pipe-area rad thick len) (+ (* 2 (area-of-washer rad (- rad thick))) (area-of-straw rad len) (area-of-straw (- rad thick) len))) ; See hw02-soln for full details. ;; This is much preferable to a version that ;; is chock full of arithmetic formulas, such as: ;; ;(define (pipe-area rad thick len) ; (* 2 pi (- (* rad rad) (* thick thick)) ; ....)) ; pluralize : int string -> string ; Given a noun and a number, combine them ; into a (grammatically correct) string. ; (Well, we won't pluralize words like 'fish' correctly, here.) ; (define (pluralize num noun) (string-append (number->string num) " " noun (if (= (abs num) 1) "" "s"))) (check-expect (pluralize 3 "cat") "3 cats") (check-expect (pluralize 1 "dog") "1 dog") (check-expect (pluralize 0 "dog") "0 dogs") (check-expect (pluralize -3 "dollar") "-3 dollars") (check-expect (pluralize -1 "dollar") "-1 dollar") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Aggregate data (structs) ; define the struct -- that is, bundle together several ; 'smaller' values into one thing: (define-struct dillo (name length alive?)) ; make-dillo : string number boolean -> dillo ; length is in meters. ; scheme auto-creates four methods: ; a consttructor ; make-dillo : string number boolean -> dillo ; and three accessors ; dillo-name : dillo -> string ; dillo-length : dillo -> number ; dillo-alive? : dillo -> boolean ; construct a dillo: (define my-pet (make-dillo "fred" 0.3 true)) ; will-fit? : dillo number -> boolean ; Does the armadillo fit in a carrier of the given length (in meters)? ; (define (will-fit? a-dillo carrier-length) (<= (dillo-length a-dillo) carrier-length)) ; Observe how the following works with the stepper, ; when we call a function: (will-fit? my-pet 0.2) (check-expect (will-fit? my-pet 0.2) false) (check-expect (will-fit? my-pet 0.4) true) (check-expect (will-fit? (make-dillo "amy" 0.5 true) 0.5) true) ;;;;;;;;;;;;;;;;;;; ; hit-with-truck: dillo -> dillo ; (define (hit-with-truck a-dillo) (make-dillo (dillo-name a-dillo) (+ 0.2 (dillo-length a-dillo)) false)) (check-expect (hit-with-truck (make-dillo "fred" 0.5 true)) (make-dillo "fred" 0.7 false)) (check-expect (hit-with-truck (make-dillo "fred" 0.7 false)) (make-dillo "fred" 0.9 false)) ;;;;;;;;;;;;;;;;;;;;;;; ;;;; Exercise in-class: ; A boa has a name and a length and a number of spots. ; a. Write a struct for boas. ; b. tell me what functions are auto-created for me (by Scheme) ; when I do this? [constructor and accessors -- what ; are their exact names?] ; c. write the function 'has-more-spots-than?' which takes ; *two* boas as inputs, and returns whetehr the first has ; more spots than the second. ; d. write the function grow-boa, which takes in a boa ; and returns one which is 0.1m longer. ;; Solution: ;; (a.) (define-struct boa (name length num-spots)) ;; (b.) ; make-boa : string number number -> boa ; boa-name : boa -> string ; boa-length : boa -> number ; boa-num-spots : boa -> number ; boa? : ANY -> boolean ;; "template for boas": ;; ANY function handling a boa might involve this: ;(define (some-boa-function boa1) ; ...(boa-num-spots boa1) ; ...(boa-length boa1) ; ...(boa-name boa1) ; ) ;; (c.) (define (has-more-spots-than? boa1 boa2) (> (boa-num-spots boa1) (boa-num-spots boa2))) (check-expect (has-more-spots-than? (make-boa "bo" 3 15) (make-boa "betty" 3.5 25)) false) ;; (d.) (define (grow-boa boa1) (make-boa (boa-name boa1) (+ 0.1 (boa-length boa1)) (boa-num-spots boa1))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Union data ;; An animal is: ;; - a boa, or ;; - a dillo. ; animal-length : animal -> number (define (animal-length an-animal) (cond [(boa? an-animal) (boa-length an-animal)] [(dillo? an-animal) (dillo-length an-animal)] )) ;;; Template for *ANY* function which process an animal: ;(define (some-animal-fun an-animal) ; (cond [(boa? an-animal) ...(boa-name an-animal) ; ...(boa-length an-animal) ; ...(boa-num-spots an-animal)] ; [(dillo? an-animal) ...(dillo-name an-animal) ; ...(dillo-length an-animal) ; ...(dillo-alive? an-animal)] ; )) (define (grow an-animal) (cond [(boa? an-animal) (grow-boa an-animal)] [(dillo? an-animal) (make-dillo (dillo-name an-animal) (+ 0.2 (dillo-length an-animal)) (dillo-alive? an-animal))] )) ;;;;;;;;; ; A data-definition: ; A list-of-numbers is ; - empty, or ; - (cons [number] [list-of-numbers]) ; built-in to scheme: ; empty [the empty list -- a constant] ; cons : ANY list -> constructed-list ; first : constructed-list -> ANY ; rest : constructed-list -> list ; empty? : ANY -> boolean ; cons? : ANY -> boolean ;; Since our data-definintion is aggregate date, ;; we'll follow those steps to come up with a template ;; for ANY function which processes a list: ;; some-lon-function : list-of-number -> number ;(define (some-lon-function a-lon) ; (cond [(empty? a-lon) ...] ; [(cons? a-lon) ...(first a-lon) ; ...(some-lon-function (rest a-lon)) ])) ; sum : list-of-number -> number (define (sum a-lon) (cond [(empty? a-lon) 0] [(cons? a-lon) (+ (first a-lon) (sum (rest a-lon)))])) (check-expect (sum empty) 0) (check-expect (sum (cons 6 empty)) 6) (check-expect (sum (cons 6 (cons 2 empty))) 8) (check-expect (sum (cons 1 (cons 6 (cons 2 empty)))) 9) ; length : list-of-number -> number (define (my-length a-lon) (cond [(empty? a-lon) 0] [(cons? a-lon) (+ 1 (my-length (rest a-lon)))])) (check-expect (my-length empty) 0) (check-expect (my-length (cons 6 empty)) 1) (check-expect (my-length (cons 6 (cons 2 empty))) 2) (check-expect (my-length (cons 17 (cons 6 (cons 2 empty)))) 3)