; CS 111 - Week 5 Lecture 1 - 2016-09-20

; remember that each cond branch starts with
;    a boolean expression --
; IF that's getting more complex than you'd like,
;    why not write a boolean auxiliary function
;    (or boolean helper function) to make your
;    life easier and less buggy?
; (and CALL that function in your cond branch
;    instead of the more-complex expression...)

; I have determined I often need to determine
;     if some Fahrenheit temperature is in a given
;     "safe" range,
;     say between 55 and 75 degrees Fahrenheit
;     inclusive?
;     which can also be written [55, 75]

; as part of my data analysis,
;     I determine that anything outside this
;     range is considered unsafe;

(define MIN-SAFE 55)
(define MAX-SAFE 75)

; signature: in-safe-range: number -> boolean
; purpose: expects a Fahrenheit temperature, and returns
;     whether or not that temperature is
;     in the safe range of [MIN-SAFE, MAX-SAFE] degrees Fahrenheit

;(define (in-safe-range temp)
;  ...
;)

; for this 3-interval data with 2 boundaries,
;    we need at least 5 appropriate tests;

(check-expect (in-safe-range 3) #false)
(check-expect (in-safe-range MIN-SAFE) #true)
(check-expect (in-safe-range 60) #true)
(check-expect (in-safe-range MAX-SAFE) #true)
(check-expect (in-safe-range 100) #false)

; say I decide to start by thinking about this as
;    3-interval data -- so I'll use a 3-branch
;    cond template:

;(define (in-safe-range temp)
;    (cond
;        [... ...]
;        [... ...]
;        [... ...]
;    )
;)

;(define (in-safe-range temp)
;    (cond
;        [(< temp MIN-SAFE) #false]
;        [(<= temp MAX-SAFE) #true]
;        [else #false]
;    )
;)

; REFACTORING because I notice two identical result expressions

;(define (in-safe-range temp)
;    (cond
;        [(or (< temp MIN-SAFE)
;             (> temp MAX-SAFE)) #false]
;        [else #true]
;    )
;)

; I might even choose to refactor one more time --
;    and write a boolean expression whose result is
;    the boolean I want...

(define (in-safe-range temp)
    (not (or (< temp MIN-SAFE)
             (> temp MAX-SAFE)))
)

;============

; rememeber that we have writing data definition comments
;     for our enumerations-style data

; DATA DEFINITION
; an ArrowKey is one of:
;     "up", "down", "left", "right"

; DATA DEFINITION
; a QuestionAnswer is one of:
;     1, 2, 3, or 4

; course style: we will write data definition comments
;    for enumeration data (and sometimes for some
;    other kinds of data)
; course style: we will give their names in CamelCase
;    starting with an uppercase letter
; course style: once we have done the above, we should
;    use those types in function signatures involving
;    that type of data;

;===================
; one more type of data from Section I, Chapter 4 of
; HtDP 2nd edition:
; Itemizations
;
; data definitions that use Itemizations GENERALIZE
;    intervals and enumerations as needed;
; Itemizations allow combinations of existing data classes
;    previously defined elsewhere;

; consider the function string->number

(string->number "354")
(string->number "moo")

; it returns a number OR #false -- how write THAT return
;    type in a signature?

; ONE way: write this as an Itemization type,
; with a data definition such as:

; DATA DEFINITION:
; a NumOrF is one of:
;     - #false
;     - a number

; THEN I could say that:

; signature: string->number: string -> NumOrF
; purpose: expects a string-version of a number,
;    and returns a number-version of it if it can,
;    and returns #false if it can't

; so if the data you are dealing with is of
;    an Itemization type,
; you probably/often need a cond to deal with
;    the possible values,
;    probably/often including a branch for each
;    item in the itemization;

; say I wanted a function that expects the result
;    of string->number and wants to add 3 to it --
;    (and if I get a #false, I want to treat that
;     #false as a 0...)

; signature: add3: NumOrF -> number
; purpose: expects a value resulting from string->number,
;    and returns the result of adding 3 to that value,
;    treating a #false as a 0

;(define (add3 a-num-or-f)
;    ...
;)

(check-expect (add3 4) 7)
(check-expect (add3 #false) 3)

; 2 items in the NumOrF itemization,
;    2 branches in my cond-template:

;(define (add3 a-num-or-f)
;    (cond
;        [... ...]
;        [... ...]
;    )
;)

; equal? can be used to compare equality
;   when more than one base type might
;   reasonable

(define (add3 a-num-or-f)
    (cond
        [(equal? a-num-or-f #false) 3]
        [else (+ a-num-or-f 3)]
    )
)