; CS 111 - Week 4 Lecture 1 - 2016-09-13 ; Sharon Tuttle ; last modified: 2016-09-13 (cleaned up a bit after class) (require 2htdp/image) (require 2htdp/universe) ;-------- ; BSL Racket has more than one expression ; for branching -- ; we're introducing one of them, ; the cond expression, ; today; ;-------- ; cond - short for conditional! ; syntax: ; ; (cond ; [bool-expr1 expr1] ; [bool-expr2 expr2] ; ... ; [bool-expr-n expr-n] ; [else expr-else] ; ) ; semantics: ; * if bool-expr1 is true, then the value ; of the whole cond expression is expr-1 ; * BUT if bool-expr1 is false, then DrRacket ; sees if bool-expr2 is true, and if so, ; the value of the whole cond expression is ; expr2 ; ... ; * IF it reaches the else, then expr-else ; is the value of this cond expression ;-------- ; AFTER you click run, ; NOTICE the dark highlighting indicating ; expressions that were NOT ; evaluated/executed ; in the following cond expression; ; ; (if the boolean expression starting a cond expression clause ; is #false, its result expression is never evaluated; ; once a #true boolean expression starting a cond expression ; clause is reached, none of the cond expression clauses ; after that are evaluated...) (cond [#false 13] [(< 1 3) "oink"] [(< 10 20) "moo"] [else "red"] ) ; let's write a function that uses a cond expression! ;-------- ; signature: greet: string number -> string ; purpose: expects a name and the hour of the ; day expressed in 24-hour time, [0, 23], ; and returns a greeting appropriate to ; the time of day: ; [0, 12) - morning ; [12, 18) - afternoon ; [18, 23] - evening ;(define (greet name time) ; ... ;) ;-------- ; OY!! when you have MULTIPLE categories ; of data, ; you need at LEAST one test PER category; ; AND -- if that data is INTERVAL data, ; (it can be expressed in interval form, ; like morning-time is [0, 12)), ; you need to ALSO test so-called BOUNDARIES ; of each interval, ; AND -- if you are checking for errors/bad data, ; TRY to test for that if you can...! (check-expect (greet "Calvin" 1) "Good morning, Calvin!") (check-expect (greet "Mary" 13) "Good afternoon, Mary!") (check-expect (greet "Steve" 20) "Good evening, Steve!") (check-expect (greet "Molly" 0) "Good morning, Molly!") (check-expect (greet "Sue" 12) "Good afternoon, Sue!") (check-expect (greet "Jimmy" 18) "Good evening, Jimmy!") (check-expect (greet "Sharon" 23) "Good evening, Sharon!") ;-------- ; ASIDE 1: ; want your function to stop with an error message? ; function error can do that: ; ; (error "desired error message") ;-------- ; ASIDE 2: ; want to write a *test* that checks if a call causes ; an error without actually having it END your ; Racket run, function check-error can do that: ; ; (check-error expr-to-test ; "error message that should result") ; (check-error (greet "Jackie" -1) "Time too small - must be in [0, 23]") (check-error (greet "Bob" 24) "Time too big - must be in [0, 23]") (check-error (greet "Barack" 0.5) "Time must be an integer in [0, 23]") ;-------- ; NEW DESIGN RECIPE STEP! ; IF your data suggests a TEMPLATE for your body, ; put in that template NOW, after writing ; your check-expressions/tests ; for interval data, you often need a cond ; expression, often with at least ; the same number of clauses as you ; have intervals ; (and sometimes more for error-checking) ;(define (greet name time) ; (cond ; [... ...] ; [... ...] ; [... ...] ; ) ;) ;-------- ; and I might add more for my error checking... ;(define (greet name time) ; (cond ; [... ...] ; [... ...] ; [... ...] ; [... ...] ; [... ...] ; [... ...] ; ) ;) ;-------- ; and then fill in each clause, handling each case ; one at a time (divide and conquer!!) ; ; (and we found out in class that the ORDER you put the ; clauses may affect how you write the boolean expression ; for a clause... ; * ...because you only REACH a clause if the boolean expressions ; of ALL the preceding clauses are #false!) (define (greet name time) (cond [(not (integer? time)) (error "Time must be an integer in [0, 23]")] [(< time 0) (error "Time too small - must be in [0, 23]")] [(< time 12) (string-append "Good morning, " name "!")] [(< time 18) (string-append "Good afternoon, " name "!")] [(<= time 23) (string-append "Good evening, " name "!")] [else (error "Time too big - must be in [0, 23]")] ) ) (greet "Calvin" 1) (greet "Mary" 13) (greet "Steve" 20) ; next: more examples of functions involving cond expressions