Please send questions to st10@humboldt.edu .

; CIS 130 - Week 5 - 2-17-10

; we need a conditional, branching statement;

; in this language in DrScheme, that's
; cond, for conditional

; syntax:
; (cond
;    [bool-expr1 result-expr1]
;    [bool-expr2 result-expr2]
;    [bool-expr3 result-expr3]
;    ...
;    [else       result-else-expr]
; )

; semantics:
;    if bool-expr1 is true, then the value
;       of this cond expression is result-expr1
;    ELSE if bool-expr2 is true, then the value
;       of the cond expression is result-expr2
;    ELSE if bool-expr3 is true, then the value
;       of the cond expression is result-expr3,
;    and so on -- as soon as a bool-expr in one
;       of these pairs is found to be true,
;       its result expression is the value of this
;       cond;
;    if none are true? the else's result-else-expr
;        is the value of the cond;
;    (the else clause is optional -- but often a
;        very good idea!)

(define TESTY 15)

(cond 
  [(< TESTY 10) "first"]
  [(< TESTY 20) "second"]
  [(> TESTY 0) "third"]
  [else "fourth"]
)

(= 3 5)
; (= "dog" "dog")  ; no, you can't use = with non-number expressions

; use equal? to compare ANY two expressions, regardless of type!

(equal? "dog" "dog")
(equal? true false)

(define OWNER "David")

(cond
  [(equal? OWNER "George") "Hi, wonderful!"]
  [(equal? OWNER "Sarah") "Hi, fabulous!"]
  [else (string-append "Welcome, " OWNER)]
)

; consider absolute value:
; in a math book, it might say something like:
;  abs-value(x) = x if x >= 0
;                 -x if x < 0

; contract: abs-value: number -> number

; purpose: expects a number, and it produces
;          that number if it is >= 0 and
;          it produces the negative of that
;          number if it is < 0

;(define (abs-value a-number)
;  ...
;)

; HOW MANY check-expects?
; AT LEAST one per "case", at least,
;    PLUS one per "boundary" between cases, if applicable
; here, we have 2 "cases", x < 0 and x >= 0, and 1 boundary, x of 0
;    so: at LEAST 3 check-expects

(check-expect (abs-value -13) 13)
(check-expect (abs-value 8) 8)
(check-expect (abs-value 0) 0)

; two cases -- so template step can result in:

;(define (abs-value a-number)
;  (cond
;    [... ...]
;    [else ...]
;  )
;)

(define (abs-value a-number)
  (cond
    [(< a-number 0) (* -1 a-number)]
    [else a-number]
  )
)

(abs-value -3)
(abs-value 4021)

; for writing boolean expressions (expressions whose result
;    have the type boolean),
; < <= > >= = equal? ...are all very useful
; here are a few more:
; and - produces true if ALL of its expressions are true

(and (< 1 3) (< 1 4) (= 5 5))
(and (< 1 3) (< 1 4) (= 4 6) (< 4 5))

(define GRADE 99)
(and (<= GRADE 100) (>= GRADE 0))

; or - produces true if AT LEAST ONE of its expression is true

(or (= 4 5) (= 5 6) (= 6 7) (= 5 5) (= 2 3) (= 7 8))
(or (< GRADE 0) (> GRADE 100))

; not - produces true if its one expression is false

(not true)
(not false)

; and sometimes a nice, precise INTERVAL notation is useful
;    for communicating exactly WHERE a boundary belongs...

; for an interval, IF you put [, that end-point is PART of
;   that interval:

; [0, 100] - this is ALL numbers from 0 to 100 INCLUSIVE --
;            0 IS in the interval, 100 IS in the interval

; IF you put (, that end-point is NOT part of the
;    interval

; [80, 90) -- 80 IS in this interval, 90 is NOT part of this interval

; custom/style: since you can't reach infinity, always put a ( before
;    an end-point of -infinity, and a ) after an end-point of infinity

;(100, infinity) - everything greater than 100, NOT including 100
;(-infinite, 15] - everything up to and including 15

; note: in writing conditional functions
; (or heck, ANY time),
; ...if you find yourself repeating some same steps several times,
;      why not write a little function to do those steps, and call
;      IT several times instead?
; ...if you find a boolean expression too big'n'hairy to conveniently
;      place as the bool-expr in an cond [... ...] pair,
;      why not write a little bool function (that produces a bool)
;      and call that instead?
; ETC. -- don't be afraid to write little "helper" functions,
;      often called AUXILIARY functions
; BUT: be sure to use the DESIGN RECIPE on EVERY function,
;      auxiliary or not...

; example of a little boolean function

; say I eventually want a function that expects a numeric grade
;    and produces the letter grade for that numeric grade

; say I also want it to return a "bad grade" string if a grade
;    is outside the interval [0, 100]

; gee, a function that tells me whether a number grade is in
;    the "legal" interval of [0, 100] might be useful --
;    I decide to write that.

; contract: legal-grade?: number -> boolean
; purpose: expects a numeric grade and produces whether
;          or not that grade is in [0, 100]

;(define (legal-grade? num-grade)
;  ...
;)

; so -- there are 5 tests needed here:
; for the case <0, 
; for the case >100,
; for the case BETWEEN 0 and 100,
; for the boundary 0,
; and for the boundary 100

(check-expect (legal-grade? -1) false)
(check-expect (legal-grade? 102) false)
(check-expect (legal-grade? 93) true)
(check-expect (legal-grade? 0) true)
(check-expect (legal-grade? 100) true)

; you COULD write this as a conditional function,
;    but you could ALSO write it as a function whose body
;    is a boolean expression - whichever you can get to work!
; (you can always refactor it later -- the tests will help
;    make sure you didn't break it in the process..)

(define (legal-grade? num-grade)
  (and (>= num-grade 0) (<= num-grade 100))
)