Designing Functions for Compound Data

Sections~#secstructures#4856> through~#secrecordsconssel#4857> suggest that the design of functions for compound data proceeds in a regular manner. First, a programmer must recognize that structures are needed. We follow the simple rule of using structures whenever the description of some object specifies several pieces of information. If we don't use structures in these cases, we quickly lose track of which data belongs to which object, especially when we write large functions which process massive amounts of data. Second, a programmer can use the structure and data definitions for the organization of a function. We use the term ``template'' when we design functions. As we will see in this and many future sections, the template matches the data definition, and the template is <#4858#>the<#4858#> essential step in the careful design of functions. To emphasize this point, we modify our function design recipe from section~#secdesign1#4859> to accommodate compound data. Most importantly, working with compound data requires adjustments in a few of the basic design steps and two new steps: data analysis and template design:
Data Analysis & Design:
Before we can develop a function, we must understand how to represent the information in our problem statement within our chosen programming language. To do so, we search the problem statement for descriptions of (relevant) objects and then design a data representation based on the results of our analysis. Until now we could use Scheme's classes of atomic data (numbers, symbols, images, etc.) to represent information. But they are not enough. If we discover that an object has N properties, we introduce a structure definition with N fields and supply a data definition that specifies what kind of data the fields may contain. Let us consider functions that process student records at a school. If a student's interesting properties for a school are
  1. the first name,
  2. the last name, and
  3. the name of the home-room teacher,
then we should represent information about a student as a structure:
<#4867#>(define-struct<#4867#> <#4868#>student<#4868#> <#4869#>(last<#4869#> <#4870#>first<#4870#> <#4871#>teacher))<#4871#>
Here is the data definition that specifies the class of student structures as precisely as possible:
A <#61193#><#4876#>student<#4876#><#61193#> is a structure:

<#70749#> <#61194#><#4877#>(make-student<#4877#>\ <#4878#>l<#4878#>\ <#4879#>f<#4879#>\ <#4880#>t)<#4880#><#61194#> <#70749#> where <#61195#><#4881#>l<#4881#><#61195#>, <#61196#><#4882#>f<#4882#><#61196#>, and <#61197#><#4883#>t<#4883#><#61197#> are symbols.

The corresponding data class contains structures like these:
  <#4888#>(make-student<#4888#> <#4889#>'<#4889#><#4890#>findler<#4890#> <#4891#>'<#4891#><#4892#>kathi<#4892#> <#4893#>'<#4893#><#4894#>matthias)<#4894#>
  <#4895#>(make-student<#4895#> <#4896#>'<#4896#><#4897#>fisler<#4897#> <#4898#>'<#4898#><#4899#>sean<#4899#> <#4900#>'<#4900#><#4901#>matthias)<#4901#> 
  <#4902#>(make-student<#4902#> <#4903#>'<#4903#><#4904#>flatt<#4904#> <#4905#>'<#4905#><#4906#>shriram<#4906#> <#4907#>'<#4907#><#4908#>matthias)<#4908#> 
Contract:
For the formulation of contracts, we can use the names of the atomic classes of data, such as <#61198#><#4911#>number<#4911#><#61198#> and <#61199#><#4912#>symbol<#4912#><#61199#>, and those names that we introduced in data definitions, such as <#61200#><#4913#>student<#4913#><#61200#>.
Template:
A function that consumes compound data is likely to compute its result from the components of its input. To remind ourselves of the components, we first design a <#4914#>template<#4914#>. For compound data, a <#61201#><#4915#>TEMPLATE<#4915#><#61201#> consists of a header and a body that lists all possible <#4916#>selector expressions<#4916#>. Each selector expression is the application of an appropriate selector primitive to a parameter that stands for a structure. In other words, a template expresses what we know about the inputs, and nothing about the outputs. We can therefore use the same template for all functions that consume the same kind of structure. Also, because a template does not express anything about the purpose of the function, we can formulate before or after we have developed examples that illustrate a function's purpose. Consider a function that consumes a <#61202#><#4917#>student<#4917#><#61202#> structure and a teacher name:
<#70750#>;; <#61203#><#4922#>process-student<#4922#> <#4923#>:<#4923#> <#4924#>student<#4924#> <#4925#>symbol<#4925#> <#4926#><#4926#><#4927#>-;SPMgt;<#4927#><#4928#><#4928#> <#4929#>?<#4929#><#4930#>?<#4930#><#4931#>?<#4931#><#61203#><#70750#>
<#4932#>(define<#4932#> <#4933#>(process-student<#4933#> <#4934#>a-student<#4934#> <#4935#>a-teacher)<#4935#> <#4936#>...)<#4936#> 
Then <#61204#><#4940#>a-student<#4940#><#61204#> is a parameter that stands for a structure and <#61205#><#4941#>a-teacher<#4941#><#61205#> stands for just a symbol. The template therefore has the following shape:
<#70751#>;; <#61206#><#4946#>process-student<#4946#> <#4947#>:<#4947#> <#4948#>student<#4948#> <#4949#>symbol<#4949#> <#4950#><#4950#><#4951#>-;SPMgt;<#4951#><#4952#><#4952#> <#4953#>?<#4953#><#4954#>?<#4954#><#4955#>?<#4955#><#61206#><#70751#>
<#4956#>(d<#4956#><#4957#>efine<#4957#> <#4958#>(process-student<#4958#> <#4959#>a-student<#4959#> <#4960#>a-teacher)<#4960#> 
  <#4961#>...<#4961#> <#4962#>(student-last<#4962#> <#4963#>a-student)<#4963#> <#4964#>...<#4964#> 
  <#4965#>...<#4965#> <#4966#>(student-first<#4966#> <#4967#>a-student)<#4967#> <#4968#>...<#4968#> 
  <#4969#>...<#4969#> <#4970#>(student-teacher<#4970#> <#4971#>a-student)<#4971#> <#4972#>...)<#4972#> 
The <#61207#><#4976#>?<#4976#><#4977#>?<#4977#><#4978#>?<#4978#><#61207#> output reminds us that we don't assume anything about the output of the function. We design every function that consumes a <#61208#><#4979#>student<#4979#><#61208#> structure using this template.
Examples:
Let us study two examples of functions that consume <#61209#><#4980#>student<#4980#><#61209#> structures. The first function, <#61210#><#4981#>check<#4981#><#61210#>, is supposed to return the last name of the student if the teacher's name is equal to <#61211#><#4982#>a-teacher<#4982#><#61211#> and <#61212#><#4983#>'<#4983#><#4984#>none<#4984#><#61212#> otherwise:
  <#4989#>(check<#4989#> <#4990#>(make-student<#4990#> <#4991#>'<#4991#><#4992#>Wilson<#4992#> <#4993#>'<#4993#><#4994#>Fritz<#4994#> <#4995#>'<#4995#><#4996#>Harper)<#4996#> <#4997#>'<#4997#><#4998#>Harper)<#4998#>
<#4999#>=<#4999#> <#5000#>'<#5000#><#5001#>Wilson<#5001#> 
  <#5002#>(check<#5002#> <#5003#>(make-student<#5003#> <#5004#>'<#5004#><#5005#>Wilson<#5005#> <#5006#>'<#5006#><#5007#>Fritz<#5007#> <#5008#>'<#5008#><#5009#>Lee)<#5009#> <#5010#>'<#5010#><#5011#>Harper)<#5011#> 
<#5012#>=<#5012#> <#5013#>'<#5013#><#5014#>none<#5014#> 
The second function, <#61213#><#5018#>transfer<#5018#><#61213#>, is supposed to produce a student structure that contains the same information as <#61214#><#5019#>a-student<#5019#><#61214#> except for the teacher field, which should be <#61215#><#5020#>a-teacher<#5020#><#61215#>:
  <#5025#>(transfer<#5025#> <#5026#>(make-student<#5026#> <#5027#>'<#5027#><#5028#>Wilson<#5028#> <#5029#>'<#5029#><#5030#>Fritz<#5030#> <#5031#>'<#5031#><#5032#>Harper)<#5032#> <#5033#>'<#5033#><#5034#>Lee)<#5034#>
<#5035#>=<#5035#> <#5036#>(make-student<#5036#> <#5037#>'<#5037#><#5038#>Wilson<#5038#> <#5039#>'<#5039#><#5040#>Fritz<#5040#> <#5041#>'<#5041#><#5042#>Lee)<#5042#> 
  <#5043#>(transfer<#5043#> <#5044#>(make-student<#5044#> <#5045#>'<#5045#><#5046#>Woops<#5046#> <#5047#>'<#5047#><#5048#>Helen<#5048#> <#5049#>'<#5049#><#5050#>Flatt)<#5050#> <#5051#>'<#5051#><#5052#>Fisler)<#5052#> 
<#5053#>=<#5053#> <#5054#>(make-student<#5054#> <#5055#>'<#5055#><#5056#>Woops<#5056#> <#5057#>'<#5057#><#5058#>Helen<#5058#> <#5059#>'<#5059#><#5060#>Fisler)<#5060#> 
Body:
The template provides as many clues for the definition of the function as the examples. As before, the goal of this step is to formulate an expression that computes the answer from the available data using other functions or Scheme's primitive. The template reminds us that the available data are the parameters and the data computed by the selector expressions. To determine what the selectors produce, we read the data definition for the structure. Let us return to our first example, <#61216#><#5064#>check<#5064#><#61216#>:
<#5069#>(d<#5069#><#5070#>efine<#5070#> <#5071#>(check<#5071#> <#5072#>a-student<#5072#> <#5073#>a-teacher)<#5073#> 
  <#5074#>(c<#5074#><#5075#>ond<#5075#> 
    <#5076#>[<#5076#><#5077#>(symbol=?<#5077#> <#5078#>(student-teacher<#5078#> <#5079#>a-student)<#5079#> <#5080#>a-teacher)<#5080#> 
     <#5081#>(student-last<#5081#> <#5082#>a-student)]<#5082#> 
    <#5083#>[<#5083#><#5084#>else<#5084#> <#5085#>'<#5085#><#5086#>none]<#5086#><#5087#>))<#5087#> 
This particular function uses two of the three selector expressions from the template. Specifically, it compares the result of the selector expression <#61217#><#5091#>(student-teacher<#5091#>\ <#5092#>a-student)<#5092#><#61217#> with <#61218#><#5093#>a-teacher<#5093#><#61218#> and, if they are equal, produces the result of <#61219#><#5094#>(student-last<#5094#>\ <#5095#>a-student)<#5095#><#61219#>. Just naming the results of the selector expressions and reading the problem statement makes the definition obvious. Similarly, the <#61220#><#5096#>transfer<#5096#><#61220#> function is easy to define using the template and the examples:
<#5101#>(d<#5101#><#5102#>efine<#5102#> <#5103#>(transfer<#5103#> <#5104#>a-student<#5104#> <#5105#>a-teacher)<#5105#> 
  <#5106#>(make-student<#5106#> <#5107#>(student-last<#5107#> <#5108#>a-student)<#5108#> 
                <#5109#>(student-first<#5109#> <#5110#>a-student)<#5110#> 
                <#5111#>a-teacher))<#5111#> 
This second function uses the same two selector expressions as the first example, but in a different way. The key observation, however, is that the template reminds us of all the information that we have available. <#5115#>When we define the function, we must use and combine the available information.<#5115#>
Figure~#figdesign3#5117> presents the recipe for compound data in tabular form. In practice, though, a function contains many functions that all work on the same class of input data. It is therefore normal to reuse the template many times, which means that examples are often constructed after the template is set up. Compare it with the design recipe in figure~#figdesign1#5118> and its extension in figure~#figdesign2#5119>. The figure suggests to make up examples before setting up the template. external ~<#5121#>Again, none of these skills are computer-specific; all of them are needed to solve all kinds of problems. Even lawyers and doctors, artisans and secretaries can benefit from laying out their work along these lines. For example, a lawyer must analyze a case, lay out the data in the case, state a purpose (goal), lay out a strategy (template), and fill in gaps. The test is then conducted in the real world, and to avoid unanticipated problems, good lawyers do mock tests.<#5121#>

#tabular5123#

<#5207#>Figure: The revised design recipe for compound data<#5207#>

<#61222#>(Refines the recipe in figure~#figdesign1#5209> (pg.~#figdesign1#5210>))<#61222#>



<#61223#>;; <#5215#>Data Analysis & Definitions<#5215#>:<#61223#>
<#5216#>(define-struct<#5216#> <#5217#>student<#5217#> <#5218#>(last<#5218#> <#5219#>first<#5219#> <#5220#>teacher))<#5220#> 
<#70752#>;; A <#61224#><#5221#>student<#5221#><#61224#> is a structure:<#70752#> 
<#70753#>;; <#61225#><#5222#>(make-student<#5222#> <#5223#>l<#5223#> <#5224#>f<#5224#> <#5225#>t)<#5225#><#61225#><#70753#> 
<#70754#>;; where <#61226#><#5226#>f<#5226#><#61226#>, <#61227#><#5227#>l<#5227#><#61227#>, and <#61228#><#5228#>t<#5228#><#61228#> are symbols.<#70754#> 
<#70755#>;; <#5229#>Contract<#5229#>: <#61229#><#5230#>subst-teacher<#5230#> <#5231#>:<#5231#> <#5232#>student<#5232#> <#5233#>symbol<#5233#> <#5234#><#5234#><#5235#>-;SPMgt;<#5235#><#5236#><#5236#> <#5237#>student<#5237#><#61229#><#70755#> 
<#70756#>;; <#5238#>Purpose<#5238#>: to create a <#61230#><#5239#>student<#5239#><#61230#> structure with a new <#70756#> 
<#70757#>;; teacher name if the teacher's name matches <#61231#><#5240#>'<#5240#><#5241#>Fritz<#5241#><#61231#><#70757#> 
<#61232#>;; <#5242#>Examples<#5242#>:<#61232#> 
<#70758#>;; <#61233#><#5243#>(subst-teacher<#5243#> <#5244#>(make-student<#5244#> <#5245#>'<#5245#><#5246#>Find<#5246#> <#5247#>'<#5247#><#5248#>Matthew<#5248#> <#5249#>'<#5249#><#5250#>Fritz)<#5250#> <#5251#>'<#5251#><#5252#>Elise)<#5252#><#61233#><#70758#> 
<#5253#>;; = <#5253#> 
<#70759#>;; <#61234#><#5254#>(make-student<#5254#> <#5255#>'<#5255#><#5256#>Find<#5256#> <#5257#>'<#5257#><#5258#>Matthew<#5258#> <#5259#>'<#5259#><#5260#>Elise)<#5260#><#61234#><#70759#> 
<#70760#>;; <#61235#><#5261#>(subst-teacher<#5261#> <#5262#>(make-student<#5262#> <#5263#>'<#5263#><#5264#>Find<#5264#> <#5265#>'<#5265#><#5266#>Matthew<#5266#> <#5267#>'<#5267#><#5268#>Amanda)<#5268#> <#5269#>'<#5269#><#5270#>Elise)<#5270#><#61235#><#70760#> 
<#5271#>;; = <#5271#> 
<#70761#>;; <#61236#><#5272#>(make-student<#5272#> <#5273#>'<#5273#><#5274#>Find<#5274#> <#5275#>'<#5275#><#5276#>Matthew<#5276#> <#5277#>'<#5277#><#5278#>Amanda)<#5278#><#61236#><#70761#> 
<#61237#>;; <#5279#>Template<#5279#>:<#61237#> 
<#70762#>;; <#61238#><#5280#>(define<#5280#> <#5281#>(process-student<#5281#> <#5282#>a-student<#5282#> <#5283#>a-teacher)<#5283#> <#61238#><#70762#> 
<#70763#>;; <#61239#> <#5284#>...<#5284#> <#5285#>(student-last<#5285#> <#5286#>a-student)<#5286#> <#5287#>...<#5287#><#61239#><#70763#> 
<#70764#>;; <#61240#> <#5288#>...<#5288#> <#5289#>(student-first<#5289#> <#5290#>a-student)<#5290#> <#5291#>...<#5291#><#61240#><#70764#> 
<#70765#>;; <#61241#> <#5292#>...<#5292#> <#5293#>(student-teacher<#5293#> <#5294#>a-student)<#5294#> <#5295#>...)<#5295#><#61241#><#70765#> 
<#61242#>;; <#5296#>Definition<#5296#>: <#61242#> 
<#5297#>(d<#5297#><#5298#>efine<#5298#> <#5299#>(subst-teacher<#5299#> <#5300#>a-student<#5300#> <#5301#>a-teacher)<#5301#> 
  <#5302#>(c<#5302#><#5303#>ond<#5303#> 
    <#5304#>[<#5304#><#5305#>(symbol=?<#5305#> <#5306#>(student-teacher<#5306#> <#5307#>a-student)<#5307#> <#5308#>'<#5308#><#5309#>Fritz)<#5309#> 
     <#5310#>(make-student<#5310#> <#5311#>(student-last<#5311#> <#5312#>a-student)<#5312#> 
                   <#5313#>(student-first<#5313#> <#5314#>a-student)<#5314#> 
                   <#5315#>a-teacher)]<#5315#> 
    <#5316#>[<#5316#><#5317#>else<#5317#> <#5318#>a-student]<#5318#><#5319#>))<#5319#> 
  
<#61243#>;; <#5320#>Tests<#5320#>:<#61243#> 
<#5321#>(subst-teacher<#5321#> <#5322#>(make-student<#5322#> <#5323#>'<#5323#><#5324#>Find<#5324#> <#5325#>'<#5325#><#5326#>Matthew<#5326#> <#5327#>'<#5327#><#5328#>Fritz)<#5328#> <#5329#>'<#5329#><#5330#>Elise)<#5330#> 
<#5331#>=<#5331#> 
<#5332#>(make-student<#5332#> <#5333#>'<#5333#><#5334#>Find<#5334#> <#5335#>'<#5335#><#5336#>Matthew<#5336#> <#5337#>'<#5337#><#5338#>Elise)<#5338#> 
<#5339#>(subst-teacher<#5339#> <#5340#>(make-student<#5340#> <#5341#>'<#5341#><#5342#>Find<#5342#> <#5343#>'<#5343#><#5344#>Matthew<#5344#> <#5345#>'<#5345#><#5346#>Amanda)<#5346#> <#5347#>'<#5347#><#5348#>Elise)<#5348#> 
<#5349#>=<#5349#> 
<#5350#>(make-student<#5350#> <#5351#>'<#5351#><#5352#>Find<#5352#> <#5353#>'<#5353#><#5354#>Matthew<#5354#> <#5355#>'<#5355#><#5356#>Amanda)<#5356#> 
<#5360#>Figure: The design recipe for compound data: a complete example<#5360#>

<#5364#>Exercise 6.5.1<#5364#> Develop templates for functions that consumes the following structures:
  1. <#61244#><#5368#>(define-struct<#5368#>\ <#5369#>movie<#5369#>\ <#5370#>(title<#5370#>\ <#5371#>producer))<#5371#><#61244#>
  2. <#61245#><#5372#>(define-struct<#5372#>\ <#5373#>boyfriend<#5373#>\ <#5374#>(name<#5374#>\ <#5375#>hair<#5375#>\ <#5376#>eyes<#5376#>\ <#5377#>phone))<#5377#><#61245#>
  3. <#61246#><#5378#>(define-struct<#5378#>\ <#5379#>cheerleader<#5379#>\ <#5380#>(name<#5380#>\ <#5381#>number))<#5381#><#61246#>
  4. <#61247#><#5382#>(define-struct<#5382#>\ <#5383#>CD<#5383#>\ <#5384#>(artist<#5384#>\ <#5385#>title<#5385#>\ <#5386#>price))<#5386#><#61247#>
  5. <#61248#><#5387#>(define-struct<#5387#>\ <#5388#>sweater<#5388#>\ <#5389#>(material<#5389#>\ <#5390#>size<#5390#>\ <#5391#>producer))<#5391#><#61248#>
None of the functions consume any other data.~ external Solution<#61249#><#61249#> <#5398#>Exercise 6.5.2<#5398#> Data definitions and templates are useful for classes of data other than structures. Here is a simple example:
A <#61250#><#5401#>very-small-int<#5401#><#61250#> is an integer between <#61251#><#5402#>1<#5402#><#61251#> and <#61252#><#5403#>4<#5403#><#61252#> (inclusively).
Develop a template for functions that consume <#61253#><#5405#>very-small-int<#5405#><#61253#>s.~ external Solution<#61254#><#61254#> <#5411#>Exercise 6.5.3<#5411#> Develop the function <#70766#><#5413#>time<#5413#><#61255#><#5414#><#5414#><#5415#>-;SPMgt;<#5415#><#5416#><#5416#><#61255#><#5417#>seconds<#5417#><#70766#>, which consumes a <#61256#><#5418#>time<#5418#><#61256#> structure (see exercise~#extimedd#5419>) and produces the number of seconds since midnight that the <#61257#><#5420#>time<#5420#><#61257#> structure represents:
<#5425#>(<#5425#><#5426#>time<#5426#><#61258#><#5427#><#5427#><#5428#>-;SPMgt;<#5428#><#5429#><#5429#><#61258#><#5430#>seconds<#5430#> <#5431#>(make-time<#5431#> <#5432#>0<#5432#> <#5433#>0<#5433#> <#5434#>2))<#5434#> <#5435#>=<#5435#> <#5436#>2<#5436#>
<#5437#>(<#5437#><#5438#>time<#5438#><#61259#><#5439#><#5439#><#5440#>-;SPMgt;<#5440#><#5441#><#5441#><#61259#><#5442#>seconds<#5442#> <#5443#>(make-time<#5443#> <#5444#>0<#5444#> <#5445#>30<#5445#> <#5446#>2))<#5446#> <#5447#>=<#5447#> <#5448#>1802<#5448#> 
<#5449#>(<#5449#><#5450#>time<#5450#><#61260#><#5451#><#5451#><#5452#>-;SPMgt;<#5452#><#5453#><#5453#><#61260#><#5454#>seconds<#5454#> <#5455#>(make-time<#5455#> <#5456#>12<#5456#> <#5457#>30<#5457#> <#5458#>2))<#5458#> <#5459#>=<#5459#> <#5460#>45002<#5460#> 
external Solution<#61261#><#61261#>