;=====
; CS 111 - Week 5 Lecture 2 - 2024-09-26
;=====

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

;=====
; DATA DEFINITION
; An Anything is an expression of any data type

;=====
; DATA DEFINITION:
; a list is one of:
; *   empty
; *   (cons Anything list)

;-----
; empty is an empty list, a list that contains NO items
; *   this ia displayed in the Interactions window as '()

empty
'()

(equal? empty
        '())

;-----
; some examples of NON-empty lists

(cons "apple" empty)

(cons "banana" (cons "apple" empty))

(cons 7 (cons "banana" (cons "apple" empty)))
(cons (star 50 "solid" "blue")
      (cons 7 (cons "banana" (cons "apple" empty))))

(cons #true (cons (star 50 "solid" "blue")
      (cons 7 (cons "banana" (cons "apple" empty)))))

;=====
; BSL Racket lists are ALWAYS, "under the hood", BUILT using
;    the given data definition above;
; BUT, like many programming languages,
;    BSL Racket does have some handy shorthands/abbreviations,
;    "syntactic sugar"
;
; there IS a list abbreviation:
;
; (list expr1 expr2 expr3 ...)
;
; BUT!!!!
;    (list expr1 expr2 expr3 ...)
;    is THE SAME "under the hood" as:
;    (cons expr1 (cons expr2 (cons expr3 ... empty ...)

(cons #true (cons (star 50 "solid" "blue")
      (cons 7 (cons "banana" (cons "apple" empty)))))

(list #true (star 50 "solid" "blue") 7 "banana" "apple")

(equal?
   (cons #true (cons (star 50 "solid" "blue")
      (cons 7 (cons "banana" (cons "apple" empty)))))
   (list #true (star 50 "solid" "blue") 7 "banana" "apple"))

;=====
; BSL Racket of course provides a suite of
;    basic list operations!

;=====
; DATA DEFINITION
; a NonEmptyList is one of:
;   * (cons Anything empty)
;   * (cons Anything list)

;-----
; we've already started using cons, but:

;=====
; signature: cons: Anything list -> list
; purpose: expects any expression and a list,
;    and returns a new list with that expression
;    as the first list value and everything else
;    in the given list as the rest of the list

(cons 1 empty)
(cons (make-color 35 45 155)
      (cons "dog"
            (cons 1 empty)))

(define STARTER-SET (cons "saucepan"
                          (cons "frying pan" empty)))
STARTER-SET

(equal? (cons "colander" STARTER-SET)
        (cons "colander" (cons "saucepan"
                               (cons "frying pan" empty))))

;=====
; signature: first: NonEmptyList -> Anything
; purpose: expects a non-empty list, and returns the
;    first element in the given list

(first (cons (make-color 35 45 155)
             (cons "dog"
                   (cons 1 empty))))

(first STARTER-SET)

;=====
; signature: rest: NonEmpty -> list
; purpose: expects a non-empty list,
;    and returns a new list of all BUT the
;    first element in the given list

;=====
; in BSL Racket, rest ALWAYS returns a *list*!!!!!

(rest (cons (make-color 35 45 155)
             (cons "dog"
                   (cons 1 empty))))

(rest STARTER-SET)

;=====
; signature: empty?: Anything -> boolean
; purpose: expects any expression with a value,
;    and returns whether it is an empty list

(empty? empty)

(empty? (cons 4 empty))

(empty? 0)

(empty? (cons 0 empty))

(empty? (cons empty empty))

;=====
; signature: list?: Anything -> boolean
; purpose: expects any expression with a value,
;    and returns whether or not it is of type list

(list? STARTER-SET)

(list? "moo")

(list? empty)

;=====
; signature: length: list -> number
; purpose: expects any list, and returns the
;    number of (top-level) elements in that list

(length (cons #true (cons (star 50 "solid" "blue")
              (cons 7 (cons "banana" (cons "apple" empty))))))

(length empty)
(length STARTER-SET)

;=====
; you CAN grab the second element of a list using:

(first (rest STARTER-SET))

(first (rest (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 empty))))))))

;=====
; you CAN grab the third element of a list using:

(first (rest (rest
                 (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 empty)))))))))

;=====
; you CAN grab the fourth element of a list using:

(first (rest (rest (rest
                       (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 empty))))))))))

;-----
; ...and so on!

;=====
; BUT, as a convenience, BSL Racket also provides
;    second:

(second STARTER-SET)

(second (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 empty)))))))

;=====
; and also third through eighth

(define NUMS (list 1 2 3 4 5 6 7 8 9 10))

(first NUMS)
(second NUMS)
(third NUMS)
(fourth NUMS)
(fifth NUMS)
(sixth NUMS)
(seventh NUMS)
(eighth NUMS)

;=====
; uncomment these to see they are not defined by Racket

;(ninth NUMS)
;(tenth NUMS)