Last time, the problem asked to write a function involving flying-objects. [Show answer from end of previous notes.] Any questions?

What if we add one more type of flying-object: a gnat, which has absolutely no associated data. How shall we represent this? How about just a symbol 'gnat? Let's look at the design recipe, and see what we need to amend.

  1. How we we change the data definiton? Easy -- in comments, add another branch:
    ;; ...or the symbol 'gnat
    
  2. Examples of data: Duh.
  3. Contract, purpose, header: unchanged, for a particular function.
  4. Test cases of function: add the case (tst-func 'gnat)
  5. Template
    1. Case Analysis: Easy -- just ask a question which will distinguish 'gnat from any other type of flying object. Discuss: contract for symbol=? vs symbol?. (What if we later add one more type of flying object, 'super-grover? What will the questions of the cond be in that situation?)
    2. Data Extraction: What pieces of data comprise a 'gnat?
    3. [Natural Recursion: We haven't talked about this step yet!]
  6. Body: fill in the answer for gnats.
  7. Test: Again easy, esp. if you keep your test cases below the function. (That is, you type the test cases before writing the function body, but you type them in below the function body.)

Recall the plane structure we used on Friday. A plane contained its brand, how many miles it flew since servicing, and the name of the mechanic who last serviced it. The airline wants to keep more detailed servicing records and decides to record the last three mechanics who serviced the plane. How would we do that?

(define-struct 3mechs (recent two-ago three-ago))
;;
;; A 3mechs is
;;   (make-3mechs symbol symbol symbol)
;; where recent is the most recent inspector's name,
;; two-ago did the inspection before that, and
;; three-ago the one before two-ago.
What is a particular example of this type of data? How would we record that the last three mechanics to service a plane were Mike, Patty, and Bubba?
(make-3mechs 'Mike 'Patty 'Bubba)
Could you write a function which processes 3-mechs? (What does its template look like?) Solution:
(define (process-3mech a-3m)
  ..(3mechs-recent a-3m)..(3mechs-two-ago a-3m)..(3mechs-three-ago a-3m)..)
Think to yourself: how would you write the function update-mechs: 3mechs, symbol --> 3mechs?
Solution:
(define (update-mechs a-3m newest-mech)
  ..(3mechs-recent a-3m)..(3mechs-two-ago a-3m)..(3mechs-three-ago a-3m)..)

; Tests
(process-3mech (make-3mechs 'Mike 'Patty 'Bubba) 'Mike)
  = (make-3mechs 'Mike 'Mike 'Patty)

To think about quickly: What is the problem with this approach of keeping track of the last 3 mechanics? Exactly -- what if the plane is new, and hasn't even been serviced 3 times? If we're lazy, we use the symbol 'not-yet-serviced. However, this precludes hiring somebody of this name!? (What if we were talking about album names, and used the flag 'self-title?) When using a sentinel value, be sure it doesn't conflict/confused with a possible real value!
Better solution: a new data definition, where name cannot possibly be confused with the sentinel value:

;; A symbol-or-false is
;;    - a symbol, or
;;    - false
;;
;; A 3mechs is:
;;    (make-3mechs symbol-or-false symbol-or-false symbol-or-false)

What if the airline wanted to track all mechanics who had ever serviced a plane, not just the last three? What struct would you define? The problem is that define-struct fixes the number of items that you glue together. However, we don't know how many mechanics will service a plane, so we can't define the structure.

We need a way to glue together arbitrarily many names of mechanics. What do you do when you want to keep track of many pieces of information? You make a list. Let's write down the mechanics who last serviced a particular plane:

Eddie
Mike 
Patty
Bubba
We need a way to turn this list into data for DrScheme. Let's start simple. What's the smallest list you can think of? Empty list. In Scheme, we write empty for the empty list. Now, we need a way to create non-empty lists.

Let's look at the list on the board. We agree that what's there is a list. Is

Mike
Patty
Bubba
a list? What's the relationship between these two lists? The first has added a name onto the second. Therefore, we can think of a list as having two parts: the name at the top and the rest of the list. Can you define a struct to capture these two pieces of information?
;; A structure for a cons ("constructed list"):
(define-struct cons (first rest))
Using this struct, how would you create a list containing Bubba?
(make-cons 'Bubba empty)
Before we continue, let's write down the data definition for a list of symbols.
;; A List-of-Symbols is either
;;	- empty, or
;;	- (make-cons symbol List-of-Symbols)

    ; Recall: this creates the functions
    ; make-cons,
    ; cons-first,
    ; cons-rest, and
    ; cons?
    ;
;; Examples of data:

empty

(make-cons 'Bubba empty)

(make-cons 'Mike 
           (make-cons 'Patty 
                     (make-cons 'Bubba
                                empty)))
Since structures are just boxes with a drawer ("field") for each piece of data, here's the picture in my mind:
(make-cons 'Bubba empty)
+==================+
# first:  'Bubba   #
#        ~~~~~~~~  #
# rest:    empty   #
#        ~~~~~~~~  #
+==================+




           (make-cons 'Patty 
                     (make-cons 'Bubba
                                empty))

+==================================+
# first:      'Patty               #
#        ~~~~~~~~~~~~~~~~~~~~~~~~  #
#                                  #
#          +==================+    #
#          # first:  'Bubba   #    #
#          #        ~~~~~~~~  #    #
#          # rest:    empty   #    #
#          #        ~~~~~~~~  #    #
# rest:    +==================+    #
#       ~~~~~~~~~~~~~~~~~~~~~~~~~~ #
+==================================+




(make-cons 'Mike 
           (make-cons 'Patty 
                     (make-cons 'Bubba
                                empty)))

+====================================================+
# first:                 'Mike                       #
#        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  #
#                                                    #
#          +==================================+      #
#          # first:      'Patty               #      #
#          #        ~~~~~~~~~~~~~~~~~~~~~~~~  #      #
#          #                                  #      #
#          #          +==================+    #      #
#          #          # first:  'Bubba   #    #      #
#          #          #        ~~~~~~~~  #    #      #
#          #          # rest:    empty   #    #      #
#          #          #        ~~~~~~~~  #    #      #
#          # rest:    +==================+    #      #
#          #       ~~~~~~~~~~~~~~~~~~~~~~~~~~ #      #
#  rest:   +==================================+      #
#        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  #
#                                                    #
+====================================================-+



(Another picture can be found in the text.)

How would you extract Mike out of this list?

(cons-first (make-cons 'Mike 
                       (make-cons 'Patty 
                                  (make-cons 'Bubba
                                             empty)))
How would extract Patty out of this list? (Hint: first, ask how you'd get the list containing everybody but mike, and work from there.)
(cons-first (cons-rest (make-cons 'Mike 
                                   (make-cons 'Patty 
                                              (make-cons 'Bubba
                                                         empty)))
Note: I write each of the two arguments to make-cons on its own line, for clarity. You can do this if you like, or you can put them all on one line, that's fine.

Trick question: what is (cons-first empty)? Yep, it's an error. Why is that a trick question? Because empty is not a constructed list! Be sure to think over the difference between lists vs. empty or make-conss. It's comparable to the difference between flying-objects vs planes or ufos or peaches or gnats.

Okay, let's try writing functions! What happens to update-mechs: List-of-Symbol, symbol --> List-of-Symbol? Well, if you think about it, this is exactly make-cons.

Note: Lists are used commonly enough, that the define-struct for cons is already built-in.
Name you'd expect name in Scheme name in Lisp
make-cons cons cons
cons-first first car
cons-rest rest cdr
cons? cons?
empty nil, '()
empty? null?
false #f, nil
true #t
(Lisp is a dialect of Scheme. These historical names are mentioned here only because you may see them in the optional texts, Hofstadter's chapters on Lisp, and The Little Schemer. Please use the modern, descriptive names instead.)


We reached here sept.10 (mon); will pick from here next time.

Question: Consider the constructor function cons, and the selectors first, rest. How do these functions relate to each other? -- mathematicians have a precise word for the relationship.
(Hint: one does what the other undoes.) Just like I can write that "cube-root(x^3) = x, for any number x", is there a similar statement governing cons/first/rest?