;===== ; CS 111 - Week 6 Lecture 1 - 2026-09-29 (require 2htdp/image) (require 2htdp/universe) ;===== ; DATA DEFINITION ; an Anything is an expression of any type ;===== ; DATA DEFINITION ; a list is one of: ; * empty ; * (cons Anything list) ; cons for CONStruct a list empty (cons 13 empty) (cons "moo" (cons 13 empty)) ;===== ; signature: cons: Anything list -> list ; purpose: expects any expression and a list, ; and returns a new list with that expression's value ; as its first element, and everything else in the given ; list as the rest of the list (define LIST-O-STUFF (cons "Zeke" (cons "moooooo" (cons "baaaaaa" (cons 7568429 (cons (circle 40 "solid" "purple") empty)))))) LIST-O-STUFF (cons "--->" LIST-O-STUFF) ;===== ; DATA DEFINITION ; a NonEmptyList is one of: ; * (cons Anything empty) ; * (cons Anything NonEmptyList) ;===== ; signature: first: NonEmptyList -> Anything ; purpose: expects a non-empty list, and returns the ; first item in that non-empty list (first LIST-O-STUFF) ;===== ; signature: rest: NonEmptyList -> list ; purpose: expects a non-empty list, and returns the list ; containing everything except the first element of the ; given list (get it? it returns the REST of the given list) ;**************************************** ; remember: rest ALWAYS returns a list!! ;***************************************** (rest LIST-O-STUFF) ;===== ; signature: empty?: Anything -> boolean ; purpose: expects any expression with a value, and returns ; whether it is an empty list (empty? "moo") (empty? LIST-O-STUFF) (empty? empty) ;===== ; signature: list?: Anything -> boolean ; purpose: expects any expression with a value, and returns ; whether it is of data type list (list? LIST-O-STUFF) (list? empty) (list? "baaaaaaa") ;===== ; signature: length: list -> number ; purpose: expects any list, and returns the number of ; (top-level) elements in that list ; ; NOTE: in the list data definition, empty ends a list -- ; it is used to "mark" the end of a list, if you will; ; the empty ending a list is NOT considered to be an element of ; that list! (length empty) (length (cons 13 empty)) (length LIST-O-STUFF) (list 1 "moo" 2 "oink" 3 (square 25 "solid" "chartreuse")) ;===== ; STARTING a template for "walking through" a list ; well, based on its data definition, a list can be ; empty, or built using cons -- ; so, a cond expression with at least two branches ; will frequently be useful for a function involving ; a non-fixed-size list: ;===== ; NOT YET A COMPLETE TEMPLATE!!!!!!!: ; ; (cond ; [... ...] ; [... ...] ; ) ;----- ; and we frequently will first want to ask ; if the given list we want to "walkk" through is empty ; and, if it ISN'T, you know it is NOT empty, ; so should be safe to use first, last with it ; ; and in that case, may want to do SOMETHING ; *combining* ; something you do with or based on the FIRST list item ; to something you do with or based on the REST of the list ;===== ; NOT YET A COMPLETE TEMPLATE!!!!!!!: ; ; (define (a-list-funct a-list) ; (cond ; [(empty? a-list) ...] ; [else ; (... (first a-list) ... ; (rest a-list) ...)] ; ) ; ) ;===== ; to help in completing this template... ; ; say I wanted to make my own version of a length function; ; ; say I wanted to name it len ;===== ; signature: len: list -> number ; purpose: expects a list, and returns the number ; of (top-level) elements in that list ;----- ; need at least one test for each bullet in ; list's data definition ; (and more are fine!) (check-expect (len empty) 0) (check-expect (len LIST-O-STUFF) 5) (define (len a-list) (cond [(empty? a-list) 0] ; when a-list is NOT empty, add 1 (for the 1st element) ; to the length of the *rest* of a-list [else (+ 1 (len (rest a-list)))] ) ) (len empty) (len LIST-O-STUFF) ;===== ; so - to FINISH this template for a function ; "walking through" a list, ; I want to ADD a CAREFUL call to the function ; itself... ;===== ; COMPLETED template for a function "walking through" a list ; ; (define (a-list-funct ... a-list ...) ; (cond ; [(empty? a-list) ...] ; [else ; (... (first a-list) ... ; (a-list-funct ... (rest a-list) ...) ...)] ; ) ; ) ;===== ; NOTE: when a function CALLS itself, ; like len does, and as this template does, ; that function is called a RECURSIVE function ; ; IMPORTANT: a recursive function NEEDS: ; * at least one BASE CASE -- at least one ; branch that does NOT call itself, to serve as ; a base, or ending point, for the repeated calls ; to itself! ; ; * each RECURSIVE CASE -- each branch that DOES call ; itself -- needs to do so on a "smaller" version of ; the given parameter, ; such that, eventually, one of the base cases WILL be ; reached ; ;----- ; Do you see how this is the case with len? and with the ; template for a function "walking through" a list? ; ; * each call to rest REMOVES one list item -- ; ; * if you keeps removing list items, you HAVE to eventually ; reach the empty list! ;===== ; Another example of a function that "walks through" a list -- ; I want a function add1-list that adds one to each item in ; a list of numbers ;===== ; signature: add1-list: list -> list ; purpose: expects a list of numbers and returns ; another list of numbers as a result of adding 1 ; to each number on the given list (check-expect (add1-list empty) empty) (check-expect (add1-list (list 1 2 3)) (list 2 3 4)) (define (add1-list num-list) (cond ; there are no numbers in an empty list - so if num-list ; is empty, just return an empty list [(empty? num-list) empty] ; but, if num-list is not empty, create a new list ; from the result of cons-ing ; 1 + the first element in num-list TO ; the result of calling add1-list on the ; rest of num-list [else (cons (add1 (first num-list)) (add1-list (rest num-list)))] ) ) (add1-list (list 1 2 3)) (add1-list (list 2 4 6 8 10 12 14 16 18 20)) ;===== ; fun fact: DrRacket has a module 2htdp/batch-io ;----- ; 2htdp/batch-io has a selection of file input and file output functions ; (as would be needed for a so-called batch program, one with ; no interactive input/output, ; that reads its needed input from file(s) and writes its ; resulting output to file(s) (require 2htdp/batch-io) ;----- ; here is an example of one of its functions that reads from ; a file (the ONLY write function it provides (!!!): ;----- ; signature: write-file: string string -> string ; purpose: expects the name of a file written as a string -- ; either its full/"absolute" name OR its name in the current ; working directory -- ; AND the string to write to that file, ; has the SIDE-EFFECT of trying to write that string ; to that file, creating the file if necessary, ; (and OVERWRITING its current contents if it exists), ; and returns the *name* of the file it wrote ;===== ; FUN FACT: you can indicate a newline within a string ; using the \n character ; (the default display of these in DrRacket's Interactions ; window is as \n, BUT they WILL appear as newlines when ; written to a file!) "=====" "(don't worry, when written to a file the \n characters below" " are treated as newlines)" "=====" "moo\nbaaa\nla la la" (write-file "sounds.txt" "moo\nbaaa\nla la la") "=====" "after running this, view the contents of the file sounds.txt" "=====" ;===== ; and here is ONE of SEVERAL functions batch-io provides for READING ; from a file: ;----- ; signature: read-words: string -> list ; purpose: expects the name of a file written as a string -- ; either its full/"absolute" name OR its name in the current ; working directory -- ; has the SIDE-EFFECT of trying to open and read the contents of ; that file, ; and returns the contents as a list of strings, with each ; white-space-separated "token"/"word" being a string in this list (read-words "sounds.txt") ;===== ; hey! since this returns a list, a read-words expression ; could be an argument to our len function! (len (read-words "sounds.txt"))