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.
;; ...or the symbol 'gnat
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?
(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 BubbaWe 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 Bubbaa 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.
(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.)
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
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.