Data Definitions

Consider the following expression:
<#4652#>(make-posn<#4652#> <#4653#>'<#4653#><#4654#>Albert<#4654#> <#4655#>'<#4655#><#4656#>Meyer)<#4656#>
It constructs a <#61143#><#4660#>posn<#4660#><#61143#> structure from two symbols. If we now apply <#61144#><#4661#>distance-to-0<#4661#><#61144#> to this structure, the computation fails miserably:
  <#4666#>(distance-to-0<#4666#> <#4667#>(make-posn<#4667#> <#4668#>'<#4668#><#4669#>Albert<#4669#> <#4670#>'<#4670#><#4671#>Meyer))<#4671#>
<#4672#>=<#4672#> <#4673#>(s<#4673#><#4674#>qrt<#4674#> 
    <#4675#>(+<#4675#> <#4676#>(square<#4676#> <#4677#>(posn-x<#4677#> <#4678#>(make-posn<#4678#> <#4679#>'<#4679#><#4680#>Albert<#4680#> <#4681#>'<#4681#><#4682#>Meyer)))<#4682#> 
       <#4683#>(square<#4683#> <#4684#>(posn-y<#4684#> <#4685#>(make-posn<#4685#> <#4686#>'<#4686#><#4687#>Albert<#4687#> <#4688#>'<#4688#><#4689#>Meyer)))))<#4689#> 
<#4690#>=<#4690#> <#4691#>(s<#4691#><#4692#>qrt<#4692#> 
    <#4693#>(+<#4693#> <#4694#>(square<#4694#> <#4695#>'<#4695#><#4696#>Albert)<#4696#> 
       <#4697#>(square<#4697#> <#4698#>(posn-y<#4698#> <#4699#>(make-posn<#4699#> <#4700#>'<#4700#><#4701#>Albert<#4701#> <#4702#>'<#4702#><#4703#>Meyer)))))<#4703#> 
<#4704#>=<#4704#> <#4705#>(s<#4705#><#4706#>qrt<#4706#> 
    <#4707#>(+<#4707#> <#4708#>(*<#4708#> <#4709#>'<#4709#><#4710#>Albert<#4710#> <#4711#>'<#4711#><#4712#>Albert)<#4712#> 
       <#4713#>(square<#4713#> <#4714#>(posn-y<#4714#> <#4715#>(make-posn<#4715#> <#4716#>'<#4716#><#4717#>Albert<#4717#> <#4718#>'<#4718#><#4719#>Meyer)))))<#4719#> 
That is, it requires us to multiply <#61145#><#4723#>'<#4723#><#4724#>Albert<#4724#><#61145#> with itself. Similarly,
<#4729#>(make-star<#4729#> <#4730#>'<#4730#><#4731#>Albert<#4731#> <#4732#>'<#4732#><#4733#>Meyer<#4733#> <#4734#>10000<#4734#> <#4735#>'<#4735#><#4736#>electric-organ)<#4736#>
does not produce a <#61146#><#4740#>star<#4740#><#61146#> structure according to our intentions. In particular, the structure is not suitable for processing by <#61147#><#4741#>increment-sales<#4741#><#61147#>. To avoid such problems and to assist with the development of functions, we must add a <#4742#>data definition<#4742#> to each structure definition. A <#61148#><#4743#>DATA DEFINITION<#4743#><#61148#> states, in a mixture of English and Scheme, how we intend to use a class of structures. For example, here is a data definition for <#61149#><#4744#>posn<#4744#><#61149#> structures:
A <#61150#><#4746#>posn<#4746#><#61150#> is a structure:

<#70746#><#61151#><#4747#>(make-posn<#4747#>\ <#4748#>x<#4748#>\ <#4749#>y)<#4749#><#61151#><#70746#> where <#61152#><#4750#>x<#4750#><#61152#> and <#61153#><#4751#>y<#4751#><#61153#> are numbers.

It says that a valid <#61154#><#4753#>posn<#4753#><#61154#> structure always contains two numbers, and nothing else. Hence, when we use <#61155#><#4754#>make-posn<#4754#><#61155#> to create a <#61156#><#4755#>posn<#4755#><#61156#> structure, we must apply it to two numbers; when a function contains selector expressions for <#61157#><#4756#>posn<#4756#><#61157#> structures, we may now assume that their result is a number. The data definition for <#61158#><#4757#>star<#4757#><#61158#> structures is only slightly more complicated:
An <#61159#><#4759#>star<#4759#><#61159#> is a structure:

<#70747#><#61160#><#4760#>(make-star<#4760#>\ <#4761#>last<#4761#>\ <#4762#>first<#4762#>\ <#4763#>instrument<#4763#>\ <#4764#>sales)<#4764#><#61160#><#70747#> where <#61161#><#4765#>last<#4765#><#61161#>, <#61162#><#4766#>first<#4766#><#61162#>, and <#61163#><#4767#>instrument<#4767#><#61163#> are symbols and <#61164#><#4768#>sales<#4768#><#61164#> is a number.

This data definition says that valid <#61165#><#4770#>star<#4770#><#61165#> structures contain symbols in the fields for <#61166#><#4771#>last<#4771#><#61166#> name, <#61167#><#4772#>first<#4772#><#61167#> name, and <#61168#><#4773#>instrument<#4773#><#61168#>, and a number in the <#61169#><#4774#>sales<#4774#><#61169#> field.

#picture4776#

<#4787#>Figure: The meaning of data definitions<#4787#>


In general, a data definition identifies a subclass of Scheme's universe of values: see figure~#figdataclass#4789>. As we have seen so far, Scheme's universe contains numbers, symbols, images, strings, chars, booleans, and many different classes of structures. Our functions, however, are intended to work only for a subclass of values. For example, <#61174#><#4790#>area-of-disk<#4790#><#61174#> consumes only numbers; <#61175#><#4791#>reply<#4791#><#61175#> from section~#secsym#4792> consumes only symbols. A few subclasses, such as <#61176#><#4793#>number<#4793#><#61176#>, already have names, because they are useful for all kinds of programming tasks. Others are only interesting in the context of a specific problem. For those cases, a programmer should introduce a data definition. The most important role of a data definition is that of a covenant between programmers and users. We expect both groups to respect such data definitions, and we expect the programmer to exploit it for the function construction. For example, when the programmer of <#61177#><#4794#>distance-to-0<#4794#><#61177#> specifies that all <#61178#><#4795#>posn<#4795#><#61178#>s contain two numbers, a user must always apply <#61179#><#4796#>distance-to-0<#4796#><#61179#> to a <#61180#><#4797#>posn<#4797#><#61180#> structure with two numbers. Furthermore, as we will discuss over the next few sections, we expect a programmer to exploit data definitions for function developments. Naturally, a data definition in English and Scheme does not prevent us from abusing <#61181#><#4798#>make-posn<#4798#><#61181#>. It is, however, a written statement of intent, and a person who willingly violates or ignores this covenant must face the consequences of ill-behaving computations.
<#4802#>Exercise 6.4.1<#4802#> Provide data definitions for the following structure definitions:
  1. <#61182#><#4805#>(define-struct<#4805#>\ <#4806#>movie<#4806#>\ <#4807#>(title<#4807#>\ <#4808#>producer))<#4808#><#61182#>
  2. <#61183#><#4809#>(define-struct<#4809#>\ <#4810#>boyfriend<#4810#>\ <#4811#>(name<#4811#>\ <#4812#>hair<#4812#>\ <#4813#>eyes<#4813#>\ <#4814#>phone))<#4814#><#61183#>
  3. <#61184#><#4815#>(define-struct<#4815#>\ <#4816#>cheerleader<#4816#>\ <#4817#>(name<#4817#>\ <#4818#>number))<#4818#><#61184#>
  4. <#61185#><#4819#>(define-struct<#4819#>\ <#4820#>CD<#4820#>\ <#4821#>(artist<#4821#>\ <#4822#>title<#4822#>\ <#4823#>price))<#4823#><#61185#>
  5. <#61186#><#4824#>(define-struct<#4824#>\ <#4825#>sweater<#4825#>\ <#4826#>(material<#4826#>\ <#4827#>size<#4827#>\ <#4828#>producer))<#4828#><#61186#>
Make appropriate assumptions about what data goes with which field.~ external Solution<#61187#><#61187#> <#4835#>Exercise 6.4.2<#4835#> Provide a structure definition and a data definition for representing points in time since midnight. A point in time consists of three numbers: hours, minutes, and seconds.~ external Solution<#61188#><#61188#> <#4842#>Exercise 6.4.3<#4842#> Provide a structure definition and a data definition for representing three-letter <#61189#><#4844#>word<#4844#><#61189#>s. A word consists of letters, which we represent with the symbols <#61190#><#4845#>'<#4845#><#4846#>a<#4846#><#61190#> through <#61191#><#4847#>'<#4847#><#4848#>z<#4848#><#61191#>.~ external Solution<#61192#><#61192#>