(require 2htdp/image)
(require 2htdp/universe)

; CS 111 - Week 5 Labs - 11:00 lab

;*******************************
;==========
; data definition:
; a list is:
;    - empty, OR
;    - (cons Anything list)
;*******************************

; our goal:
; develope a TEMPLATE for a function that "walks through"
;     a list

; consider its definition!
; there are two items in that definition --
;     that implies there will often be at least two options
;     for a function walking through a list

; list function template - PART 1, INCOMPLETE
;==============================================
; (define (a-list-funct a-list ...)
;     (cond
;         [(empty? a-list) ...]
;         [else (... (first a-list) ...
;                    (rest a-list) ...)]
;     )
; )

; I decide to try this INCOMPLETE template
;    in the course of writing a function
;    that tells me how many "top-level" items
;    are in a list

; signature: len: list -> number
; purpose: expects a list, and returns how many
;    "top-level" items are in that list

;(define (len a-list)
;    ...
;)

; list data definition has two items --
; need at least 2 tests!

(check-expect (len empty)
              0)
(check-expect (len (cons 1 (cons "moo" (cons #true empty))))
              3)

; pasting in my INCOMPLETE cond-template for a function
;    walking through a list
;    (and changing the parameter variable as needed

;(define (len a-list)
;     (cond
;         [(empty? a-list) ...]
;         [else (... (first a-list) ...
;                    (rest a-list) ...)]
;     )
;)

(define (len a-list)
     (cond
         [(empty? a-list) 0]
         [else (+ 1
                  (len (rest a-list)))]
     )
)

; WHAT!!! a function can call itself!
;    yes, if it does so CAREFULLY!
;    ...recursive data definitions often lead
;       to recursive FUNCTIONS,
;       a function that calls itself;
;
;    this is safe WHEN:
;    *   there is at least ONE non-recursive branch
;        (that does NOT call itself)
;    *   you can show/prove that repeated calls
;        of a recursive branch eventually lead
;        to a non-recursive branch

; list function template - COMPLETE
;==============================================
; (define (a-list-funct a-list ...)
;     (cond
;         [(empty? a-list) ...]
;         [else (... (first a-list) ...
;                    (a-list-funct (rest a-list) ...) ...)]
;     )
; )

; ANOTHER example...
; now, I want to consider lists of numbers!
; I'd like to be able to add 1 to each element in a
;    list of numbers

; I decide I want a data definition for the specialized
;    type of list

; DATA DEFINITION
; a NumberList is one of:
;    - empty
;    - (cons number NumberList)

; hey, I could write a template for a function
;    walking through a NumberList!

; NumberList function template
;==============================================
; (define (num-list-funct a-num-list ...)
;     (cond
;         [(empty? a-num-list) ...]
;         [else (... (first a-num-list) ...
;                    (num-list-funct (rest a-num-list) ...) ...)]
;     )
; )

; signature: add1-list: NumberList -> NumberList
; purpose: expects a list of numbers, and returns
;    a new list in which each number is 1 larger
;    than its counterpart in the given list

;(define (add1-list a-num-list)
;    ...
;)

; make sure you have at LEAST a test for each item
;    in the NumberList's data definition!

(check-expect (add1-list empty) empty)
(check-expect (add1-list (cons 12 (cons 12.5 (cons 12.6 empty))))
              (cons 13 (cons 13.5 (cons 13.6 empty))))

;(define (add1-list a-num-list)
;; (define (num-list-funct a-num-list ...)
;;     (cond
;;         [(empty? a-num-list) ...]
;;         [else (... (first a-num-list) ...
;;                    (num-list-funct (rest a-num-list) ...) ...)]
;;     )
;; )    
;)

; I change the names in the template to match MY
;   function's names (function name and parameter name),
;   and then chop out the parts I don't need,
;   resulting in:

;(define (add1-list a-num-list)
;     (cond
;         [(empty? a-num-list) ...]
;         [else (... (first a-num-list) ...
;                    (add1-list (rest a-num-list) ...) ...)]
;     )  
;)

(define (add1-list a-num-list)
     (cond
         [(empty? a-num-list) empty]
         [else (cons (+ 1 (first a-num-list))
                     (add1-list (rest a-num-list)))]
     )  
)

(add1-list (cons 12 (cons 12.5 (cons 12.6 empty))))