Structure Definitions

In the preceding section we explored one particular class of structures: the <#61050#><#4194#>posn<#4194#><#61050#> structures. A <#61051#><#4195#>posn<#4195#><#61051#> structure combines two numbers, and it is useful to represent pixels. If we wish to represent employee records or points in three-dimensional space, however, <#61052#><#4196#>posn<#4196#><#61052#>s are useless. DrScheme therefore permits programmers to define their own structures so that they can represent all kinds of objects with a fixed number of properties. A <#61053#><#4197#>STRUCTURE DEFINITION<#4197#><#61053#> is, as the term says, a new form of definition. Here is DrScheme's definition of <#61054#><#4198#>posn<#4198#><#61054#>:
<#4203#>(define-struct<#4203#> <#4204#>posn<#4204#> <#4205#>(x<#4205#> <#4206#>y))<#4206#>  
When DrScheme evaluates this structure definition, it creates three operations for us, which we can use to create data and to program:
  1. <#61055#><#4211#>make-posn<#4211#><#61055#>, the <#61056#><#4212#>CONSTRUCTOR<#4212#><#61056#>, which creates <#61057#><#4213#>posn<#4213#><#61057#> structures;
  2. <#61058#><#4214#>posn-x<#4214#><#61058#>, a <#61059#><#4215#>SELECTOR<#4215#><#61059#>, which extracts the x-coordinate;
  3. <#61060#><#4216#>posn-y<#4216#><#61060#>, also a selector, which extracts the y-coordinate.
In general, the names of these new operations are created by prefixing the name of the structure with ``make-'' and by postfixing the name with all the field names. This naming convention appears to be complicated but, with some practice, it is easy to remember. Now consider the following example:
<#4222#>(define-struct<#4222#> <#4223#>entry<#4223#> <#4224#>(name<#4224#> <#4225#>zip<#4225#> <#4226#>phone))<#4226#>
The structure represents a simplified entry into an address book. Each <#61061#><#4230#>entry<#4230#><#61061#> combines three values. We also say that each <#61062#><#4231#>entry<#4231#><#61062#> structure has <#4232#>three<#4232#> fields: <#61063#><#4233#>name<#4233#><#61063#>, <#61064#><#4234#>zip<#4234#><#61064#>, and <#61065#><#4235#>phone<#4235#><#61065#>. Because there are three fields, the constructor <#61066#><#4236#>make-entry<#4236#><#61066#> consumes three values. For example,
<#4241#>(make-entry<#4241#> <#4242#>'<#4242#><#4243#>PeterLee<#4243#> <#4244#>15270<#4244#> <#4245#>'<#4245#><#4246#>606-7771)<#4246#>
creates an <#61067#><#4250#>entry<#4250#><#61067#> structure with <#61068#><#4251#>'<#4251#><#4252#>PeterLee<#4252#><#61068#> in the <#61069#><#4253#>name<#4253#><#61069#>-field, <#61070#><#4254#>15270<#4254#><#61070#> in the <#61071#><#4255#>zip<#4255#><#61071#>-field, and <#61072#><#4256#>'<#4256#><#4257#>606-7771<#4257#><#61072#> in the <#61073#><#4258#>z<#4258#><#61073#>-field. One way to think of a structure is as a box with as many compartments as there are fields:

#picture4260#

The italicized labels name the fields. By putting values in the compartments, we illustrate specific <#61086#><#4276#>entry<#4276#><#61086#> structures. The <#61087#><#4277#>define-struct<#4277#><#61087#> definition of <#61088#><#4278#>entry<#4278#><#61088#> also introduces new selectors:

<#4283#>entry-name<#4283#>    <#4284#>entry-zip<#4284#>    <#4285#>entry-phone<#4285#>
Here is how we can use the first one:
  <#4293#>(entry-name<#4293#> <#4294#>(make-entry<#4294#> <#4295#>'<#4295#><#4296#>PeterLee<#4296#> <#4297#>15270<#4297#> <#4298#>'<#4298#><#4299#>606-7771))<#4299#>
<#4300#>=<#4300#> <#4301#>'<#4301#><#4302#>PeterLee<#4302#> 
If we give the structure a name,
<#4310#>(define<#4310#> <#4311#>phonebook<#4311#> <#4312#>(make-entry<#4312#> <#4313#>'<#4313#><#4314#>PeterLee<#4314#> <#4315#>15270<#4315#> <#4316#>'<#4316#><#4317#>606-7771))<#4317#>
then we can use the selectors in the <#4321#>Interactions<#4321#> window to extract the data from the three fields:
  <#4326#>(entry-name<#4326#> <#4327#>phonebook)<#4327#>
<#4328#>=<#4328#> <#4329#>'<#4329#><#4330#>PeterLee<#4330#> 
  <#4331#>(entry-zip<#4331#> <#4332#>phonebook)<#4332#> 
<#4333#>=<#4333#> <#4334#>15270<#4334#> 
  <#4335#>(entry-phone<#4335#> <#4336#>phonebook)<#4336#> 
<#4337#>=<#4337#> <#4338#>'<#4338#><#4339#>606-7771<#4339#> 
Put more graphically, a constructor creates a box with several compartments and puts values in it. A selector reveals the contents of a particular compartment, but leaves the box alone. Here is one final example, a structure for representing rock stars:
<#4347#>(define-struct<#4347#> <#4348#>star<#4348#> <#4349#>(last<#4349#> <#4350#>first<#4350#> <#4351#>instrument<#4351#> <#4352#>sales))<#4352#>
It defines the class of <#61089#><#4356#>star<#4356#><#61089#> structures, each of which has four fields. Accordingly, we get five new primitive operations:
<#4361#>make-star<#4361#>   <#4362#>star-last<#4362#>   <#4363#>star-first<#4363#>    <#4364#>star-instrument<#4364#>    <#4365#>star-sales<#4365#>
The first is for constructing <#61090#><#4369#>star<#4369#><#61090#> structures; the others are selector operations for extracting values from a <#61091#><#4370#>star<#4370#><#61091#> structure. To create a <#61092#><#4371#>star<#4371#><#61092#> structure, we apply <#61093#><#4372#>make-star<#4372#><#61093#> to three symbols and a positive integer:
<#4377#>(make-star<#4377#> <#4378#>'<#4378#><#4379#>Friedman<#4379#> <#4380#>'<#4380#><#4381#>Dan<#4381#> <#4382#>'<#4382#><#4383#>ukelele<#4383#> <#4384#>19004)<#4384#>
<#4385#>(make-star<#4385#> <#4386#>'<#4386#><#4387#>Talcott<#4387#> <#4388#>'<#4388#><#4389#>Carolyn<#4389#> <#4390#>'<#4390#><#4391#>banjo<#4391#> <#4392#>80000)<#4392#> 
<#4393#>(make-star<#4393#> <#4394#>'<#4394#><#4395#>Harper<#4395#> <#4396#>'<#4396#><#4397#>Robert<#4397#> <#4398#>'<#4398#><#4399#>bagpipe<#4399#> <#4400#>27860)<#4400#> 
To select the first name of a star structure called <#61094#><#4404#>E<#4404#><#61094#>, we use
<#4409#>(star-first<#4409#> <#4410#>E)<#4410#>
Other fields are extracted with other selectors.
<#4416#>Exercise 6.3.1<#4416#> Consider the following structure definitions:
  1. <#61095#><#4419#>(define-struct<#4419#>\ <#4420#>movie<#4420#>\ <#4421#>(title<#4421#>\ <#4422#>producer))<#4422#><#61095#>
  2. <#61096#><#4423#>(define-struct<#4423#>\ <#4424#>boyfriend<#4424#>\ <#4425#>(name<#4425#>\ <#4426#>hair<#4426#>\ <#4427#>eyes<#4427#>\ <#4428#>phone))<#4428#><#61096#>
  3. <#61097#><#4429#>(define-struct<#4429#>\ <#4430#>cheerleader<#4430#>\ <#4431#>(name<#4431#>\ <#4432#>number))<#4432#><#61097#>
  4. <#61098#><#4433#>(define-struct<#4433#>\ <#4434#>CD<#4434#>\ <#4435#>(artist<#4435#>\ <#4436#>title<#4436#>\ <#4437#>price))<#4437#><#61098#>
  5. <#61099#><#4438#>(define-struct<#4438#>\ <#4439#>sweater<#4439#>\ <#4440#>(material<#4440#>\ <#4441#>size<#4441#>\ <#4442#>producer))<#4442#><#61099#>
What are the names of the constructors and the selectors that each of them adds to Scheme? Draw box representations for each of these structures.~ external Solution<#61100#><#61100#> <#4449#>Exercise 6.3.2<#4449#> Consider the following structure definition
<#4456#>(define-struct<#4456#> <#4457#>movie<#4457#> <#4458#>(title<#4458#> <#4459#>producer))<#4459#>
and evaluate the following expressions:
  1. <#61101#><#4464#>(movie-title<#4464#>\ <#4465#>(make-movie<#4465#>\ <#4466#>'<#4466#><#4467#>ThePhantomMenace<#4467#>\ <#4468#>'<#4468#><#4469#>Lucas))<#4469#><#61101#>
  2. <#61102#><#4470#>(movie-producer<#4470#>\ <#4471#>(make-movie<#4471#>\ <#4472#>'<#4472#><#4473#>TheEmpireStrikesBack<#4473#>\ <#4474#>'<#4474#><#4475#>Lucas))<#4475#><#61102#>
Now evaluate the following expressions, assuming <#61103#><#4477#>x<#4477#><#61103#> and <#61104#><#4478#>y<#4478#><#61104#> stand for arbitrary symbols:
  1. <#61105#><#4480#>(movie-title<#4480#>\ <#4481#>(make-movie<#4481#>\ <#4482#>x<#4482#>\ <#4483#>y))<#4483#><#61105#>
  2. <#61106#><#4484#>(movie-producer<#4484#>\ <#4485#>(make-movie<#4485#>\ <#4486#>x<#4486#>\ <#4487#>y))<#4487#><#61106#>
Formulate equations that state general laws concerning the relationships of <#61107#><#4489#>movie-title<#4489#><#61107#> and <#61108#><#4490#>movie-producer<#4490#><#61108#> and <#61109#><#4491#>make-movie<#4491#><#61109#>.~ external Solution<#61110#><#61110#>
Functions both consume and produce structures. Suppose we need to record an increase of sales for one of our stars. This act should be recorded in the star's record. To do so, we should have a function that consumes a <#61111#><#4499#>star<#4499#><#61111#> structure and produces a <#61112#><#4500#>star<#4500#><#61112#> structure with the same information except for the sales component. Let's assume for now that the function adds 20000 to the star's sales. First, we write down a basic description of the function, using our contract, header, and purpose format:
<#70742#>;; <#61113#><#4505#>increment-sales<#4505#> <#4506#>:<#4506#> <#4507#>star<#4507#> <#4508#><#4508#><#4509#>-;SPMgt;<#4509#><#4510#><#4510#> <#4511#>star<#4511#><#61113#><#70742#>
<#70743#>;; to produce a <#61114#><#4512#>star<#4512#><#61114#> record like <#61115#><#4513#>a-star<#4513#><#61115#> with <#61116#><#4514#>20000<#4514#><#61116#> more sales <#70743#> 
<#4515#>(define<#4515#> <#4516#>(increment-sales<#4516#> <#4517#>a-star)<#4517#> <#4518#>...)<#4518#> 
Here is an example of how the function should process <#61117#><#4522#>star<#4522#><#61117#> structures:
  <#4527#>(increment-sales<#4527#> <#4528#>(make-star<#4528#> <#4529#>'<#4529#><#4530#>Abba<#4530#> <#4531#>'<#4531#><#4532#>John<#4532#> <#4533#>'<#4533#><#4534#>vocals<#4534#> <#4535#>12200))<#4535#>
<#4536#>=<#4536#> <#4537#>(make-star<#4537#> <#4538#>'<#4538#><#4539#>Abba<#4539#> <#4540#>'<#4540#><#4541#>John<#4541#> <#4542#>'<#4542#><#4543#>vocals<#4543#> <#4544#>32200))<#4544#> 
The three sample <#61118#><#4548#>star<#4548#><#61118#> structures from above are also good examples of potential inputs.
<#70744#>;; <#61119#><#4553#>increment-sales<#4553#> <#4554#>:<#4554#> <#4555#>star<#4555#> <#4556#><#4556#><#4557#>-;SPMgt;<#4557#><#4558#><#4558#> <#4559#>star<#4559#><#61119#><#70744#>
<#70745#>;; to produce a <#61120#><#4560#>star<#4560#><#61120#> record like <#61121#><#4561#>a-star<#4561#><#61121#> with <#61122#><#4562#>20000<#4562#><#61122#> more sales<#70745#> 
<#4563#>(d<#4563#><#4564#>efine<#4564#> <#4565#>(increment-sales<#4565#> <#4566#>a-star)<#4566#> 
  <#4567#>(make-star<#4567#> <#4568#>(star-last<#4568#> <#4569#>a-star)<#4569#> 
             <#4570#>(star-first<#4570#> <#4571#>a-star)<#4571#> 
             <#4572#>(star-instrument<#4572#> <#4573#>a-star)<#4573#> 
             <#4574#>(+<#4574#> <#4575#>(star-sales<#4575#> <#4576#>a-star)<#4576#> <#4577#>20000)))<#4577#> 
<#61123#>Figure: The complete definition of <#4581#>increment-sales<#4581#><#61123#>
The <#61124#><#4583#>increment-sales<#4583#><#61124#> function must construct a new <#61125#><#4584#>star<#4584#><#61125#> structure with <#61126#><#4585#>make-star<#4585#><#61126#>, but to do so, it must also extract the data in <#61127#><#4586#>a-star<#4586#><#61127#>. After all, almost all of the data in <#61128#><#4587#>a-star<#4587#><#61128#> is a part of the <#61129#><#4588#>star<#4588#><#61129#> structure produced by <#61130#><#4589#>increment-sales<#4589#><#61130#>. This suggests that the definition of <#61131#><#4590#>increment-sales<#4590#><#61131#> contains expressions that extract the four fields of <#61132#><#4591#>a-star<#4591#><#61132#>:
<#4596#>(d<#4596#><#4597#>efine<#4597#> <#4598#>(increment-sales<#4598#> <#4599#>a-star)<#4599#> 
  <#4600#>...<#4600#> <#4601#>(star-last<#4601#> <#4602#>a-star)<#4602#> <#4603#>...<#4603#> 
  <#4604#>...<#4604#> <#4605#>(star-first<#4605#> <#4606#>a-star)<#4606#> <#4607#>...<#4607#> 
  <#4608#>...<#4608#> <#4609#>(star-instrument<#4609#> <#4610#>a-star)<#4610#> <#4611#>...<#4611#> 
  <#4612#>...<#4612#> <#4613#>(star-sales<#4613#> <#4614#>a-star)<#4614#> <#4615#>...<#4615#> <#4616#>)<#4616#> 
As we have seen with the examples, the function adds <#61133#><#4620#>20000<#4620#><#61133#> to <#61134#><#4621#>(star-sales<#4621#>\ <#4622#>a-star)<#4622#><#61134#> and assembles the four pieces of data into a <#61135#><#4623#>star<#4623#><#61135#> structure with <#61136#><#4624#>make-star<#4624#><#61136#>. Figure~#figincrementsales#4625> contains the complete definition.
<#4628#>Exercise 6.3.3<#4628#> Provide a structure definition that represents the airforce's jet fighters. Assume that a fighter's essential properties are
  1. designation (<#61137#><#4632#>'<#4632#><#4633#>f22<#4633#><#61137#>, <#61138#><#4634#>'<#4634#><#4635#>tornado<#4635#><#61138#>, or <#61139#><#4636#>'<#4636#><#4637#>mig22<#4637#><#61139#>),
  2. acceleration,
  3. top-speed, and
  4. range.
Then develop the function <#61140#><#4639#>within-range<#4639#><#61140#>. The function consumes a fighter record and the distance of a target from the (fighter's) base. It determines whether the fighter can reach the intended target. Also develop the function <#61141#><#4640#>reduce-range<#4640#><#61141#>. The function consumes a fighter record and produces a similar one, with range reduced to 80 of its original value.~ external Solution<#61142#><#61142#>