;; 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 lect05b) (read-case-sensitive #t) (teachpacks ((lib "universe.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "universe.ss" "teachpack" "2htdp"))))) ;; lect05b notes: We repeat the 'book' and 'dvd' and 'lib-item' data types, ;; and then we'll make lists of those types. ;; Search for to 'Sep.30' or 'lob0' for that portion. ; A book is: ; (make-book [string] [string] [number] [boolean]) ; (define-struct book (title author pages copyR?)) ;(define (book->string a-book) ; ... (book-title a-book) ; ... (book-author a-book) ; ... (book-pages a-book) ; ... (book-copyR? a-book) ; ) ; Just so we compile [this function was written in lect02a:] (define (blend s1 s2) s1) ; Examples of the data: (define b0 (make-book "The Soul of Wit" "Shorty" 0 false)) (define b1 (make-book "The Cat in the Hat" "Seuss" 31 true)) (define b2 (make-book "The Dictionary" "Webster" 547 false)) ; Note that 'define-struct' automagically creates ; functions for us: ; Constructor: ; make-book: string, string, number, boolean -> book ; Selectors: ; book-title : book -> string ; book-author : book -> string ; book-pages : book -> number ; book-copyR? : book -> boolean ; Predicate: ; book? : ANY -> boolean ; read-time: book -> number ; How long does it take to read `a-book`, in hours? ; #;(define (read-time a-book) -99) (check-expect (read-time (make-book "The Soul of Wit" "Shorty" 0 false)) 0) (check-expect (read-time b1) (+ 1 2/60)) ;;; AFTER making the test cases, we go back and write the code: ; read-time: book -> number ; How long does it take to read the book, in hours? ; (define (read-time a-book) (* (book-pages a-book) 2 1/60)) ; book->string : book -> string ; Convert a book into a nice printable format for users. ; (define (book->string a-book) (string-append (book-title a-book) ", by " (book-author a-book) " (" (number->string (book-pages a-book)) "pp)" (if (book-copyR? a-book) " (c)" ""))) (check-expect (book->string b1) "The Cat in the Hat, by Seuss (31pp) (c)") (check-expect (book->string (make-book "The Soul of Wit" "Shorty" 0 false)) "The Soul of Wit, by Shorty (0pp)") ; derive-from : book, string, number -> book ; (define (derive-from a-book new-author pages-added) (make-book (string-append "Son of " (book-title a-book)) (string-append (book-author a-book) " and " new-author) (+ (book-pages a-book) pages-added) (book-copyR? a-book))) (check-expect (derive-from (make-book "The Soul of Wit" "Shorty" 0 false) "Dr Barland" 10) (make-book "Son of The Soul of Wit" "Shorty and Dr Barland" 10 false)) ;;;;; Sep.14 ;;;;;; ;; vandalize : book -> book ;; (define (vandalize a-book) (make-book (blend (book-title a-book) (book-author a-book)) (book-author a-book) (quotient (book-pages a-book) 2) (book-copyR? a-book))) (check-expect (vandalize b1) (make-book (blend "The Cat in the Hat" "Seuss") "Seuss" 15 true)) (check-expect (book-pages b1) 31) ;;;;; Sep.16 ;;;;;; ; A DVD is: ; (make-dvd [string] [number]) ; where `time` is the running time in minutes (non-negative) ; and title is non-empty string. (define-struct dvd (title time)) (define botr (make-dvd "Bored of the Rings" 4892)) (define dvd0 (make-dvd " " 0)) (define dvd1 (make-dvd "The Hurt Locker" 131)) (define dvd2 botr) ; A lib-item is either ; - a book, or ; - a dvd. ;; Functions which handle lib-items: ;; time-to-waste : lib-item -> number ;; Return how long the lib-item takes to be experienced (in hours) (define (time-to-waste li) (cond [(book? li) (read-time li)] [(dvd? li) (/ (+ (dvd-time li) 5) 60)] [else (error 'time-to-waste "Expected a lib-item, got ~v." li)])) (check-expect (time-to-waste (make-book "The Soul of Wit" "Shorty" 0 false)) 0) (check-expect (time-to-waste (make-dvd "Bored of the Rings" 4892)) (/ (+ 4892 5) 60)) ;; Template for a function handling *any* type of lib-item: ;(define (fun-for-lib-item li) ; (cond [(book? li) ...(book-title li) ; ...(book-author li) ; ...(book-pages li) ; ...(book-copyR? li)] ; [(dvd? li) ...(dvd-time li) ; ...(dvd-title li)] ; [else (error 'fun-for-lib-item "Expected a lib-item, got ~v." li)])) ; li-title: lib-item -> string ; Return the title of *any* lib-item ; (whether a book, a dvd, or some variant we might add in the future). (define (li-title li) (cond [(book? li) (book-title li)] [(dvd? li) (dvd-title li)] [else (error 'li-title "Expected a lib-item, got ~v." li)])) ; ; Here's where we wish that we could use sub-classing, ; with the supertype lib-item having a single selector, ; rather than having to do a cond, and choose which selector ; to use (either book-title or dvd-title, depending). ; ... it turns out, plt-scheme does allow structs that inherit. ; (Separately, it also has an object system, too.) ; We won't explore those here though, since you already know O.O. ;;;; lect03c (Sep.18) ; A bookshelf is: ; (make-bookshelf [string] [book] [book]) ; (define-struct bookshelf (label b1 b2)) (define bs1 (make-bookshelf "fiction" b1 (make-book "Soul of Wit" "Shorty" 0 false))) ; total-read-time: bookshelf -> number ; How long does it take to read every ; book on the shelf, in hours? (define (total-read-time bs) (+ (read-time (bookshelf-b1 bs)) (read-time (bookshelf-b2 bs)))) (check-expect (total-read-time bs1) 62/60) ;;;; A template for any function ;;;; processing bookshelves: ;(define (total-read-time bs) ; ...(bookshelf-label bs) ; ...(bookshelf-b1 bs) ; ...(bookshelf-b2 bs)) ; ; A ls is ; (make-ls [lib-item] ; [lib-item] ; [lib-item]) (define-struct ls (li1 li2 li3)) ; Examples: (make-ls b1 botr b1) (define (ls->string a-ls) (string-append (li-title (ls-li1 a-ls)) ", " (li-title (ls-li2 a-ls)) ", " (li-title (ls-li3 a-ls)))) (check-expect (ls->string (make-ls b1 botr b1)) "The Cat in the Hat, Bored of the Rings, The Cat in the Hat") ;;;;;;;;;;;;;;;;; lect05b : Sep.30 ;;;;;;;;;;;;;;;; ; Review from yesterday: ; Data definition: ; a [list-of-num] is ; - empty, or ; - (cons [num] [list-of-num]) ;;; make a list-of-books ;; A list-of-books is ;; - empty, or ;; - (cons [book] [list-of-books]) (define lob0 empty) (define lob1 (cons b1 empty)) (define lob2 (cons b2 (cons b1 empty))) (define lob3 (cons b0 (cons b2 (cons b1 empty)))) ;;; write: total-pages ;; total-pages : list-of-books -> number (define (total-pages a-lob) (cond [(empty? a-lob) 0] [(cons? a-lob) (+ (book-pages (first a-lob)) (total-pages (rest a-lob)))])) ;(define (fun-for-lob a-lob) ; (cond [(empty? a-lob) ...] ; [(cons? a-lob) ... (first a-lob) ; ...(fun-for-lob (rest a-lob))])) (check-expect (total-pages lob0) 0) (check-expect (total-pages lob1) 31) (check-expect (total-pages lob2) 578) (check-expect (total-pages lob3) 578) ;;; write: vandalize-all ; vandalize-all : list-of-books -> list-of-books (define (vandalize-all a-lob) (cond [(empty? a-lob) empty] [(cons? a-lob) (cons (vandalize (first a-lob)) (vandalize-all (rest a-lob)))])) ;; we "map" the function vandalize ;; onto every book in a-lob. (check-expect (vandalize-all lob0) empty) (check-expect (vandalize-all lob1) (cons (vandalize b1) empty)) (check-expect (vandalize-all lob2) (cons (vandalize b2) (cons (vandalize b1) empty))) (check-expect (vandalize-all lob3) (cons (vandalize b0) (cons (vandalize b2) (cons (vandalize b1) empty)))) ;;; write: filter-pd ; return a list of all the non-copyrighted books in a-lob ; filter the non-copyrighted the books from a-lob (define (filter-pd a-lob) (cond [(empty? a-lob) empty] [(cons? a-lob) (if (not (book-copyR? (first a-lob))) (cons (first a-lob) (filter-pd (rest a-lob))) (filter-pd (rest a-lob)))])) (check-expect (filter-pd empty) empty) (check-expect (filter-pd (cons b1 empty)) empty) (check-expect (filter-pd (cons b2 (cons b1 empty))) (cons b2 empty)) (check-expect (filter-pd (cons b0 (cons b2 (cons b1 empty)))) (cons b0 (cons b2 empty))) ;; within each branch of a case analysis, ;; you can extract fields and use them. ;; BUT: Don't do case analysis inside of anything else: ;; if an extracted field is a union type, call a function on it, no cond. ;;; libitem-list-total-time : list-of-lib-items -> number ;;; (define (libitem-list-total-time a-loli) (cond [(empty? a-loli) ...] [(cons? a-loli) ...(time-to-waste (first a-loli)) ...(libitem-list-total-time (rest a-loli))])) ;; Write 'contains?' ;; Trace sum, from lect04c.ss ;; Let.