;; 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-reader.ss" "lang")((modname list-intro-before) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f () #f))) ; We will (a) move to intermediate-student language, and (b) require: (require "student-extras.rkt") ; ; This gives us `define/contract` and `define-struct/c`, where ; the contracts/types are no longer commented-out. #| Follow the design recipe (the final version!): ---- Per data type: 1. Choose datatype definition 2. Give some examples of the data 3. Template: a. If handling a product-type, pull out each piece (field). b. If handling a union type, include a cond w/ one branch per variant. b2. (if a variant is itself a struct, you in-line step (a) inside the cond-branch) c. Inventory: In all cases, think about what *type* (each piece) is, and think of some functions that process that type. d. Add the natural recursive call (as appropriate) ---- Per function: 4. write test cases 5. (a-d): copy the template; complete header, purpose, contract/type; stub the "..."s. 6. Inventory with values: Consider a particular test case, and think about what *specific* *value* of each sub-expression template has. 7. complete the body 8. run tests |# #| Definition: argument: the value passed into a function parameter: a function's local variable/identifier which is initialized from the arguments (each time the function is *called*). |# #| Today's+Tomorrow's outline: 1. Design recipe (recall, v.quickly). 2. datatype def'n for: list (including the non-built-in-way) 3. processing a list: sum write: length write: contains? (return a bool) write: triple-every-even (return a *list*) write: my-max (note bad run-time) learn: let* |# ; to-model: a list of numbers. ; ; Datatype Definition: #;(define (list? val) (or (empty? val) (cons? val))) #;(define-struct/c cons ([first any?] [rest list?])) ; interpretation: `first` tacked to the front of the list `rest`. ; examples of the data '() (cons 42 '()) (cons 38 (cons 42 '())) (first (cons 38 (cons 42 '()))) = 38 (rest (cons 38 (cons 42 '()))) = (cons 42 '()) (first (rest (cons 38 (cons 42 '())))) ; '() is the empty list; there is also the named-constant `empty`, bound to it. ; Note that we could use any value we like, to represent the empty-list -- just so long ; as we can distinguish it from a cons-struct. ; Examples of data: '() (cons 3 '()) (cons 4 (cons 3 '())) (cons 5 (cons 4 (cons 3 '()))) (first (cons 5 (cons 4 (cons 3 '())))) (rest (cons 5 (cons 4 (cons 3 '())))) ; The constructor isn't *actually* `make-cons`, but instead just `cons`. ; The selectors aren't *actually* `cons-first`, but instead just `first` ; and not `cons-rest`, but instead just `rest`. ; ; There *is* a predicate `cons? : (-> any? boolean?)`. ; Also, there is a predicate to test for the empty-list: `empty? : (-> any? boolean?)` ;; template, for *any* function handling a list: ; (define/contract (func-for-list a-lon) (-> list? ...?) (cond [(empty? a-lon) ...] [(cons? a-lon) (... (first a-lon) (func-for-list (rest a-lon)))])) (check-expect (sum '()) 0) (check-expect (sum (cons 3 '())) 3) (check-expect (sum (cons 4 (cons 3 '()))) 7) (check-expect (sum (cons 5 (cons 4 (cons 3 '())))) 12) (define/contract (sum a-lon) (-> list? number?) ; return the sum of the numbers in `a-lon` (cond [(empty? a-lon) 0] [(cons? a-lon) (+ (first a-lon) (sum (rest a-lon)))])) ; inventory with values: suppose that `a-lon` stands for ; (cons 5 (cons 4 (cons 3 '()))). ; So what is (first a-lon) in this case? 5 <--- ; So what is (rest a-lon) in this case? ; (cons 4 (cons 3 '())) <--- ; So what is (sum (rest a-lon)) in this case? 7 <--- ; sub-question: what is (rest a-lon) in this case? (cons 2 (cons 4 '())) ; So what should my answer be in this case? 12 (check-expect (sum '()) 0) (check-expect (sum (cons 4 '())) 4) (check-expect (sum (cons 2 (cons 4 '()))) 6) (check-expect (sum (cons 3 (cons 2 (cons 4 '())))) 9) (check-expect (my-length '()) 0) (check-expect (my-length (cons 4 '())) 1) (check-expect (my-length (cons 2 (cons 4 '()))) 2) (check-expect (my-length (cons 99 (cons 2 (cons 4 '())))) 3) (define/contract (my-length a-lon) (-> list? natural?) (cond [(empty? a-lon) 0] [(cons? a-lon) (+ 1 (my-length (rest a-lon)))])) (check-expect (contains? 93 '()) #false) (check-expect (contains? 3 (cons 3 '())) #true) (check-expect (contains? 93 (cons 93 '())) #true) (check-expect (contains? 93 (cons 7 '())) #false) (check-expect (contains? 93 (cons 7 (cons 93 '()))) #true) (check-expect (contains? 93 (cons 93 (cons 7 '()))) #true) (check-expect (contains? 93 (cons 3 (cons 7 '()))) #false) (check-expect (contains? 93 (cons 44 (cons 93 (cons 7 '())))) #true) (check-expect (contains? 93 (cons 44 (cons 3 (cons 7 '())))) #false) #;(define/contract (contains? target a-lon) ...TODO...) #| truth-table: inputA inputB | desired-answer ------ ------- | -------------- #false #false | #false #false #true | #true #true #false | #true #true #true | #true |# ;; further self-practice: ; index-of : list-of-number, number -> natnum ; return the index of the first occurrence of `target` in `a-lon` ; pre-condition: `target` *must* occur in the `a-lon`. ; get-at : natnum, list-of-T -> T ; Return the `i`th element of `a-lon` (0-based index) ; pre-condition: `(< i (length a-lon))` (an exception will be thrown). ; ;Challenge: ; next : T, list-of-T -> T ; Return the item in `items` that comes *after* `target` (wrapping around if needed). ; pre-condition: `target` occurs in `items` (so per force, `items` can't be empty) ; ;;; This is difficult when the target is the *last* item of the list. ;;; In that case, when recurring to '(), ;;; we need to know more than just the list -- the function also ;;; needs to be told what to return when it reaches '(). ;;; HINT: Use a helper, which gets one extra additional argument. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Functions *returning* a list: ; triple-every-even (leaving odd numbers untouched) ; (check-expect (tee '()) ...) (check-expect (tee (cons 4 '())) (cons 12 '())) (check-expect (tee (cons 7 '())) (cons 7 '())) (check-expect (tee (cons 2 (cons 4 '()))) (cons 6 (cons 12 '()))) (check-expect (tee (cons 93 (cons 2 (cons 4 '())))) (cons 93 (cons 6 (cons 12 '())))) (define/contract (tee a-lon) (-> list? ...) ; "triple-every-even" -- return another list like `a-lon`, ; but every even number is tripled (and odd numbers are unchanged). ...)