;; CS101 Lecture Notes #9 ;; Spring 2013 ;; ; ; An alternate way to define functions (used in the 2nd edition ; of the "How to Design Programs" book): ; ; The function definitions below are equivalent: ; ; (define func1 (define (func1 x) ; (lambda (x) (* x x x x)) ; (* x x x x))) ; ; The reason we are using the form on the left (and not the ; one on the right) is that the form on the left is one you ; will see in CMPU145 and other higher-level courses that use ; LISP or Racket. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DATA STRUCTURE FOR DATA OF ARBITRARY SIZE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Lists! ;; ;; The data structure provided in Racket to hold arbitrary ;; amounts of data is called a *list*: a sequentially arranged ;; grouping of values ending with the empty list. ;; ;; A list is a recursive data structure in that larger lists ;; contain smaller lists with the same structure. ;; ;; Most interesting problems in computer science involve an ;; arbitrarily large amount of data, (often a huge amount) for ;; solving real problems. ;; ;; The smallest possible list is the empty list, represented by ;; the word empty, or '(). ;; ;; You must remember this: ;; THE EMPTY LIST IS AT THE CORE OF EVERY NON-EMPTY LIST. ;; THE EMPTY LIST IS AT THE CORE OF EVERY NON-EMPTY LIST. ;; THE EMPTY LIST IS AT THE CORE OF EVERY NON-EMPTY LIST. ;; THE EMPTY LIST IS AT THE CORE OF EVERY NON-EMPTY LIST. ;; ;; FUNCTIONS FOR LISTS: ; ; CONS: The *cons* function is one way to make non-empty lists ; by adding one new element at a time to the left side ; or first position of an existing list. ; ; The contract for the cons function looks like this: ; (cons any (listof any)) -> (listof any) ; ; In contracts, lists can be specified by slightly ; different terminology: (listof numbers), (listof strings) ; ; There is another way we will refer to lists that we'll see ; after we cover data definitions for lists. ; ; cons is called a list CONSTRUCTOR and the FIELDS that can be ; accessed in a non-empty list are called *first* and *rest*. ; ; ; FIRST, REST, EMPTY?, AND CONS? ; ; The contract for the FIRST function looks like this: ; (first (cons Y (listof X))) -> Y ; first returns the leftmost element of the list. ; ; The contract for the REST function looks like this: ; (rest (cons Y (listof X))) -> (listof X) ; rest returns the list without the first element. ; ; The empty? function checks for the empty list, with the ; contract: ; (empty? anything) -> boolean ; ; The cons? function checks for a non-empty list, with ; contract: ; (cons? anything) -> boolean ; ;(check-expect (first (cons 8 empty)) ?) ;(check-expect (rest (cons 8 empty)) ?) ;; a longer list with a name: (define listy (cons 8 (cons 7 (cons 6 empty)))) ;; DRAW PICTURE OF listy ;(check-expect (first listy) ?) ;(check-expect (first (rest listy)) ?) ;(check-expect (rest listy) ?) ;(check-expect (first (rest (rest listy))) ?) ;; Lists don't have to hold just one kind of type, e.g.: (define multlisty (cons "bird" (cons 3 (cons true empty)))) ;(check-expect (first multlisty) ?) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;DATA DEFINITION FOR A LIST OF 4 NUMBERS: ;;A list of 4 numbers (lo4n) is ;; (cons w (cons x (cons y (cons z empty)))) ;;where w x y and z are numbers ;; AFTER THE ABOVE COMMENTS ARE WRITTEN, WE CAN TREAT LO4N AS ;; A DEFINED DATA TYPE. NOTE THAT AN LO4N IS STILL A FIXED SIZED ;; DATA STRUCTURE BECAUSE IT CONTAINS EXACTLY 4 NUMBERS ;; Suppose you are asked to define a function that consumes ;; a lo4n and produces the sum of the numbers. ;; Contract: (sum-lo4n lo4n) -> number ;; Header: (define sum-lo4n (lambda (a-lo4n) ... )) ;; Purpose: sum the numbers in a-lo4n ; ; One difference between using non-empty data lists versus ; built-in Racket entities is that you may need to create named ; examples of a list before you can test your function on a ; list. ; ; So after the contract and purpose, create some example lo4ns ; for testing purposes. ; ;; EXAMPLES AND TESTS: (define LONY (cons 4 (cons 3 (cons 2 (cons 1 empty))))) (define LONX (cons 5 (cons 6 (cons 4 (cons 2 empty))))) (define LONZ (cons 0 (cons 0 (cons 0 (cons 0 empty))))) ; ; Templates are used in the HTDP books to remind you of the ; functions you can use with a particular data structure. ; ; For the most part, we will skip writing templates because ; they are as time-consuming as writing the function itself. ; If you find templates useful, you may choose to write a ; template for every given data structure. ; ; A typical template is shown below: ; ;; TEMPLATE for functions that consume a lo4n: ;; (fun-for-lo4n lo4n) -> ??? ;; template for function that consumes a lo4n ;; (define fun-for-lo4n ;; (lambda (a-lo4n) ;; ... (first a-lo4n) ... ;; ... (first (rest a-lo4n)) ... ;; ... (first (rest (rest a-lo4n))) ... ;; ... (first (rest (rest (rest a-lo4n)))) ...) ;;Pre-function tests: ; (check-expect (sum-lo4n LONY) 10) ; (check-expect (sum-lo4n LONX) 17) ; (check-expect (sum-lo4n LONZ) 0) ; Function definition: ; (define sum-lo4n ; (lambda (a-lo4n) ; ;; get first item on list ; ;; get second item on list ; ;; get third item on list ; ;; get last item on list ; ) ; Post-function trials: ; (sum-lo4n LONY) "(sum-lo4n LONY) => 10" ; (sum-lo4n LONX) "(sum-lo4n LONX) => 17" ; (sum-lo4n LONZ) "(sum-lo4n LONZ) => 0" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; What if we had lists of over 100 elements? The sum-lo4n function ;; would not work for longer lists and it would be tedious to write ;; such a function for 100 elements. ;; It helps to think of a list as a "self-referential" or "recursive" ;; data structure. Normally, we will restrict all the elements in the ;; list to have the same type by making the type explicit in our data ;; definitions: ;; ; ; EXAMPLE LIST DATA DEFINITION FOR A LIST OF NUMBERS (lon): ; ; A list of numbers (lon) is either ; 1. empty, or ; 2. a non-empty list that was made using (cons n numlist), where ; n is a number and numlist is a lon ; ; NOTE: lon is now a data type that we can refer to in function ; contracts, just like we do numbers, strings, images, etc ; ; Notice that the second case makes a reference to its own data ; type by using an lon in (cons n numlist), a self-reference. ; ; You will see that, with lists, THE SHAPE OF FUNCTIONS THAT CONSUME ; A LIST MATCH THE SHAPE OF THE DATA DEFINITION. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Creating a TEMPLATE for a function that consumes a lon. ;; This template contains a cond statement with 2 clauses: ;; Contract: (fun-for-lon lon) -> ??? ;; Header: (define fun-for-lon (lambda (a-lon) ...)) ;; Purpose: template for function that consumes an lon ;; (define fun-for-lon ;; (lambda (a-lon)... ;; (cond ;; ;; BASE CASE ;; [...] ;; ;; RECURSIVE CASE ;; [else ...])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; In-class example 2: ;; Write a function that consumes a list of numbers and produces the ;; sum of those numbers. ;; Contract: (sum-all lon) -> number ;; Header: (define sum-all (lambda (numlist) )) ;; Purpose: produce the sum of the numbers in numlist ;; Example lons: ;; We could test our function on the lo4n constants we defined above, ;; but we can define lists with more than 4 elements for a better ;; set of test cases: (define ONES (cons 1 (cons 1 (cons 1 (cons 1 (cons 1 empty)))))) (define PRIMES (cons 3 (cons 7 (cons 17 (cons 23 (cons 37 (cons 1 empty))))))) (define EVENS (cons 10 (cons 8 (cons 6 (cons 2 (cons 4 (cons 12 empty))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;Pre-tests: ; (check-expect (sum-all ONES) 5) ; (check-expect (sum-all PRIMES) 88) ; (check-expect (sum-all EVENS) 42) ;; 42!!! ; (check-expect (sum-all empty) 0) ;; ALWAYS test the empty list ;; Function: ;(define sum-all ; (lambda (numlist) ;;Post-tests: ; "(sum-all ONES) => 5" (sum-all ONES) ; "(sum-all PRIMES) => 88" (sum-all PRIMES) ; "(sum-all EVENS) => life, the universe, and everything" (sum-all EVENS) ; "(sum-all EVENS) => 0"(sum-all empty) (newline) ; ; Write a function called ANY-MATCHES? that takes in a string STR and a ; list of strings LOS and returns true if any of the strings in LOS is ; the same as STR. If none of the strings in LOS is the same as STR, ; return false. ; ; It may help you to ; write this function using a decision statement and then re-write the ; function using only a combination of the logical operators NOT, AND ; and OR. ; ; When you're thinking about how to write this function, think about ; what should be returned in the base case, when LOS is empty. In the ; recursive case, either the string at (first LOS) is equal to STR, or ; keep looking. ; ;; Contract: ;; Header: ;; Purpose: ;; Pre-function Tests: ;; Function definition: