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

; CS 111 - Week 5 Labs - 1:00 lab - 2016-09-23

; we want to work our way to a template
;    for a function that does something to
;    each thing in a (parameter) list --
;    that "walks through" a list

;-----
; data definition:
; an Anything is an expression of ANY type

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

; START of a template for a function that "walks through"
; a list -- its definition has 2 items, both had better
; be handled; (the template says there are at LEAST
; two branches)
;
; NOT COMPLETE YET:
; (define (a-list-funct a-list ...)
;    (cond
;        [(empty? a-list) ...]
;        [else (... (first a-list)
;                   (rest a-list) ...)]
;    )
; )

; say I decide I want a function that tells me
;    the length of a list --
;    the number of "top-level" items 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 definition has 2 items in it --
;    better have at least 2 tests!!

(check-expect (len empty)
              0)
(check-expect (len (cons "banana" (cons 3 (cons #false empty))))
              3)

; paste in template, modify parameter names within
;    to match my parameter names

;(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)))]
    )
)

; if a function has a parameter based on recursive data,
;    in terms of self-referential data,
;    that function is often self-referential as well --
;    it CALLS itself (carefully!!!)

; a function that calls itself is a RECURSIVE function.
; a recursive function is fine IF:
; *   at least ONE of its branches does not call itself
; *   each branch that DOES call itself does so
;     such that, if calls keep being done,
;     one of the non-recursive branches MUST eventually
;     be reached

(len (cons "banana" (cons 3 (cons #false empty))))

; SO: this call to itself should be in the template:

; COMPLETE template for a function that "walks through"
;    a list:
;================================================
; (define (a-list-funct a-list ...)
;    (cond
;        [(empty? a-list) ...]
;        [else (... (first a-list)
;                   (a-list-funct (rest a-list) ...) ...)]
;    )
; )

; another example:
; I decide I want to add 1 to all of the numbers in
;    a list of numbers

; hey, I want a specialized kind of list!

; DATA DEFINITION:
; a NumberList is:
;    - empty, OR
;    - (cons number NumberList)

; and here's a template for a function
;    "walking through" a NumberList:
;================================================
; (define (numlist-funct a-num-list ...)
;    (cond
;        [(empty? a-num-list) ...]
;        [else (... (first a-num-list)
;                   (numlist-funct (rest a-num-list) ...) ...)]
;    )
; )

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

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

; NumberList has two items in its definition,
;    I need at least 2 tests:

(check-expect (add1-list empty)
              empty)
(check-expect (add1-list (cons 4 (cons 7 (cons 1.2 empty))))
              (cons 5 (cons 8 (cons 2.2 empty))))

; paste in the template,
; CHANGE the function and parameter names in the template
;    to YOUR function's name and parameter(s)' name(s)

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

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

(add1-list (cons 4 (cons 7 (cons 1.2 empty))))