define-struct is DrScheme's mechanism for creating records (new forms of compound data). Whenever you create a new form of compound data, you should write down three things: 1. A comment (the data definition or data model) that indicates the types of each field of the compound data 2. The define-struct call that creates your new form of data 3. Examples of data created with the new definition Here are these three items for our boa definition from class ;; A boa is a ;; (make-boa symbol number symbol) (define-struct boa (name length food)) (make-boa 'Slinky 15 'pets) (make-boa 'Slim 10 'lettuce) define-struct creates a number of functions for you. For the boa case, DrScheme creates the following functions: make-boa : symbol number symbol -> boa (constructor) boa-name : boa -> symbol (selectors) boa-length : boa -> number boa-food : boa -> symbol boa? : value -> boolean (recognizer) Here's another example ;; An armadillo is a ;; (make-armadillo number boolean) (define-struct armadillo (length dead?)) (make-armadillo 3 true) (make-armadillo 6 false) This defines the following functions: make-armadillo : number symbol -> armadillo armadillo-length : armadillo -> number armadillo-dead? : armadillo -> boolean armadillo? : value -> boolean We can write programs over these new kinds of data as we've done over numbers and symbols: ;; run-over : armadillo -> armadillo ;; return a dead armadillo that is one unit longer than the input armadillo (define (run-over adillo) (make-armadillo (+ (armadillo-length adillo) 1) true)) Sometimes, we want to write programs that process a collection of types of data. For example, we might want to write programs to manage a zoo of both boas and armadillos. Consider a program longer-than?, which checks whether a boa or armadillo is longer than a given length. What would the contract look like? Here's one possibility: ;; longer-than? : (boa or armadillo) number -> boolean Is this contract good or bad? What happens if we later add tigers to our zoo? Then giraffes? And so on. For flexibility, we really want a single name by which we can refer to the collection of animals in our zoo. So, we want something like ;; longer-than? : animal number -> boolean This is more flexible (and cleaner), but we haven't defined what an animal is. ;; An animal is either ;; - a boa, or ;; - an armadillo Notice that this data definition doesn't require a define-struct because we are not trying to build a new kind of data. We are merely introducing a name by which we can refer to several variants of a kind of data (this is analagous to creating a class animal with subclasses boa and armadillo -- you expect to make boas and armadillos, but never generic animals). Why is this more flexible than listing the types of animals in the contract though? Wouldn't we have to add tiger, giraffe, etc to our animal definition just as we'd have to add them to our longer-than? contract? [left as an exercise to the reader] How do we write programs over animals? Let's fill in a bit more of longer-than? (the ... are the pieces we still need to fill in): ;; longer-than? : animal number -> boolean ;; determine whether an animal is longer than a given length (define (longer-than? ani len) (cond [(boa? ani) ...] [(armadillo? ani) ...])) We know that the input is an animal. Our data definition for animal tells us that an animal is one of two types of data. So, we need a cond to tell us which type of animal we have. We can proceed to fill in the rest of the program: ;; longer-than? : animal number -> boolean ;; determine whether an animal is longer than a given length (define (longer-than? ani len) (cond [(boa? ani) (> (boa-length ani) len)] [(armadillo? ani) (> (armadillo-length ani) len)])) Notice there is no animal-length operation, because we never wrote (define-struct animal ...). If you want an animal-length function, you have to define it from scratch.