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)) How would we record that the last three mechanics to service a plane were Mike, Patty, and Bubba? (make-3mechs 'Mike 'Patty 'Bubba) Write a program Bubba-serve? which takes a 3mechs structure and returns true if Bubba has serviced the plane, false otherwise. Our contract, purpose, and template: ;; Bubba-serve? : 3mechs -> bool ;; determine whether Bubba is one of the 3 mechanics (define (Bubba-serve? a-3mech) ...(3mechs-recent a-3mechs)... ...(3mechs-two-ago a-3mechs)... ...(3mechs-three-ago a-3mechs)...) Fill in the template for the answer ;; Bubba-serve? : 3mechs -> bool ;; determine whether Bubba is one of the 3 mechanics (define (Bubba-serve? a-3mech) (or (symbol=? 'Bubba (3mechs-recent a-3mechs)) (symbol=? 'Bubba (3mechs-two-ago a-3mechs)) (symbol=? 'Bubba (3mechs-three-ago a-3mechs)))) 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? (define-struct lst (first rest)) Using this struct, how would you create a list containing Bubba? (make-lst '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-lst name a-los) ;; where name is a symbol and a-los is a list-of-symbols How would you define the list containing Mike, Patty, and Bubba? (make-lst 'Mike (make-lst 'Patty (make-lst 'Bubba empty))) How would you get Mike out of this list? (lst-first (make-lst 'Mike (make-lst 'Patty (make-lst 'Bubba empty)))) How would get Patty out of this list? (lst-first (lst-rest (make-lst 'Mike (make-lst 'Patty (make-lst 'Bubba empty))))) Let's re-write our earlier program Bubba-serve? to consume a list of symbols rather than a 3mechs structure. ;; Bubba-serve? : list-of-symbols -> bool ;; determine whether Bubba is a mechanic in the list (define (Bubba-serve? a-los) ...) What about the template? How many cases in the data definition? Two, so we need a cond with two branches: ;; Bubba-serve? : list-of-symbols -> bool ;; determine whether Bubba is a mechanic in the list (define (Bubba-serve? a-los) (cond [... ...] [... ...])) What question do we ask to detect the empty case? Scheme provides the operator empty?. So our template looks as follows: ;; Bubba-serve? : list-of-symbols -> bool ;; determine whether Bubba is a mechanic in the list (define (Bubba-serve? a-los) (cond [(empty? a-los) ...] [(lst? a-los) ...(lst-first a-los)...(lst-rest a-los)...])) Have we exploited all of the information in the data definition? Almost. There's one piece of information there that we overlooked. Notice how the definition says that a-los is a list-of-symbols? The definition itself is called a list-of-symbols. We want to record this relationship in the data definition itself. We do this by drawing an arrow from the second occurrence to the original definition. Now, return to the template. Do we know anything else about (first a-los)? Just that it is a symbol, so we don't have to do anything else with it. What about (rest a-los)? Well, we know that it is a list-of-symbols. Do we have a way to check whether Bubba is in a list of symbols? Yes, using Bubba-serve? So, we can draw an arrow from (rest a-los) back to Bubba-serve?. What do you notice about this arrow? It looks just like the arrow in the data definition! We want to include the arrow in our template. The arrow tells us to use Bubba-serve? to process lists of symbols. Since we can't type the arrow into DrScheme, we'll do the next best thing: call the program Bubba-serve? on (rest a-los) in the template. ;; Bubba-serve? : list-of-symbols -> bool ;; determine whether Bubba is a mechanic in the list (define (Bubba-serve? a-los) (cond [(empty? a-los) ...] [(lst? a-los) ...(lst-first a-los) ...(Bubba-serve? (lst-rest a-los))...]))