Structure Definitions

We still have to understand the syntax and semantics of one more Scheme construct: <#61903#><#8715#>define-struct<#8715#><#61903#>. When we define a structure, we really define several primitive operations: a constructor, several selectors, and a predicate. Hence, <#61904#><#8716#>define-struct<#8716#><#61904#> is by far the most complex Scheme construct we use. A structure definition is a third form of definition. The keyword <#8717#>define-struct<#8717#> distinguishes this form of definition from function and variable definitions. The keyword is followed by a name and a sequence of names enclosed in parentheses: #tex2html_wrap_inline72910# = (<#61906#><#8720#>define-struct<#8720#><#61906#> #tex2html_wrap_inline72912# (#tex2html_wrap_inline72914#)) . The names in a <#61910#><#8725#>define-struct<#8725#><#61910#> definition must be chosen as if they were variables or function names, though none of them are variables or function names. Here is a simple example:
  <#8730#>(define-struct<#8730#> <#8731#>point<#8731#> <#8732#>(x<#8732#> <#8733#>y<#8733#> <#8734#>z))<#8734#> <#8735#>.<#8735#> 
Since <#61911#><#8739#>point<#8739#><#61911#>, <#61912#><#8740#>x<#8740#><#61912#>, <#61913#><#8741#>y<#8741#><#61913#>, and <#61914#><#8742#>z<#8742#><#61914#> are variables and the parentheses are placed properly, it is a proper definition of a structure. In contrast,
  <#8747#>(define-struct<#8747#> <#8748#>(point<#8748#> <#8749#>x<#8749#> <#8750#>y<#8750#> <#8751#>z))<#8751#>
and
  <#8759#>(define-struct<#8759#> <#8760#>point<#8760#> <#8761#>x<#8761#> <#8762#>y<#8762#> <#8763#>z)<#8763#>
are improper definitions because <#61915#><#8767#>define-struct<#8767#><#61915#> is not followed by a single variable name and a sequence of variables in parentheses. A <#61916#><#8768#>define-struct<#8768#><#61916#> definition introduces new primitive operations. The names of these operations are formed from those that occur in the definition. Suppose a data structure definition has the following shape:
  <#8773#>(define-struct<#8773#> <#8774#>c<#8774#> <#8775#>(s-1<#8775#> <#8776#>...<#8776#> <#8777#>s-n))<#8777#>
Then Scheme introduces the following primitive operations:
  1. <#61917#><#8782#>make-c<#8782#><#61917#>: a <#8783#>constructor<#8783#>;
  2. <#61918#><#8784#>c-s-1<#8784#>\ <#8785#>...<#8785#>\ <#8786#>c-s-n<#8786#><#61918#>: a series of <#8787#>selectors<#8787#>; and
  3. <#61919#><#8788#>c?<#8788#><#61919#>: a <#8789#>predicate<#8789#>.
These primitives have the same status as <#61920#><#8791#>+<#8791#><#61920#>, <#61921#><#8792#>-<#8792#><#61921#>, or <#61922#><#8793#>*<#8793#><#61922#>. Before we can understand the rules that govern these new primitives, however, we must return to the definition of values. After all, the purpose of <#61923#><#8794#>define-struct<#8794#><#61923#> is to introduce a new class of values: structures. Simply put, the set of values no longer consists of just constants, but also of structures, which compound several values into one. In terms of our grammar of values, we must add one clause per <#61924#><#8795#>define-struct<#8795#><#61924#>:

#tabular8797#

Let us return to the <#61928#><#8805#>points<#8805#><#61928#> structures. Since the list of fields contains three names, <#61929#><#8806#>(make-point<#8806#>\ <#8807#>u<#8807#>\ <#8808#>v<#8808#>\ <#8809#>w)<#8809#><#61929#> is a value if <#61930#><#8810#>u<#8810#><#61930#>, <#61931#><#8811#>v<#8811#><#61931#>, and <#61932#><#8812#>w<#8812#><#61932#> are values. Now we are in a position to understand the evaluation rules of the new primitives. If <#61933#><#8813#>c-s-1<#8813#><#61933#> is applied to a <#61934#><#8814#>c<#8814#><#61934#> structure, it returns the first component of the value. Similarly, the second selector extracts the second component, the third selector the third component, and so on. The relationship between the new data constructor and the selectors is best characterized with n equations:

<#8819#>(c-s-1<#8819#> <#8820#>(make-c<#8820#> <#8821#>V-1<#8821#> <#8822#>...<#8822#> <#8823#>V-n))<#8823#> <#8824#>=<#8824#> <#8825#>V-1<#8825#>
                  <#8826#>#tex2html_wrap_inline72922#<#8826#> 
<#8827#>(c-s-n<#8827#> <#8828#>(make-c<#8828#> <#8829#>V-1<#8829#> <#8830#>...<#8830#> <#8831#>V-n))<#8831#> <#8832#>=<#8832#> <#8833#>V-n<#8833#> 
where <#61935#><#8837#>V-1<#8837#>\ <#8838#>...<#8838#>\ <#8839#>V-n<#8839#><#61935#> is a sequence of values that is as long as <#61936#><#8840#>s-1<#8840#>\ <#8841#>...<#8841#>\ <#8842#>s-n<#8842#><#61936#>. For our running example, we get the equations
<#8847#>(point-x<#8847#> <#8848#>(make-point<#8848#> <#8849#>V<#8849#> <#8850#>U<#8850#> <#8851#>W))<#8851#> <#8852#>=<#8852#> <#8853#>V<#8853#>
<#8854#>(point-y<#8854#> <#8855#>(make-point<#8855#> <#8856#>V<#8856#> <#8857#>U<#8857#> <#8858#>W))<#8858#> <#8859#>=<#8859#> <#8860#>U<#8860#> 
<#8861#>(point-z<#8861#> <#8862#>(make-point<#8862#> <#8863#>V<#8863#> <#8864#>U<#8864#> <#8865#>W))<#8865#> <#8866#>=<#8866#> <#8867#>W<#8867#> 
In particular, <#61937#><#8871#>(point-y<#8871#>\ <#8872#>(make-point<#8872#>\ <#8873#>3<#8873#>\ <#8874#>4<#8874#>\ <#8875#>5))<#8875#><#61937#> is equal to <#61938#><#8876#>4<#8876#><#61938#>, and <#61939#><#8877#>(point-x<#8877#>\ <#8878#>(make-point<#8878#>\ <#8879#>(make-point<#8879#>\ <#8880#>1<#8880#>\ <#8881#>2<#8881#>\ <#8882#>3)<#8882#>\ <#8883#>4<#8883#>\ <#8884#>5))<#8884#><#61939#> evaluates to <#61940#><#8885#>(make-point<#8885#>\ <#8886#>1<#8886#>\ <#8887#>2<#8887#>\ <#8888#>3)<#8888#><#61940#> because the latter is also a value. The predicate <#61941#><#8889#>c?<#8889#><#61941#> can be applied to any value. It returns <#61942#><#8890#>true<#8890#><#61942#> if the value is of kind <#61943#><#8891#>c<#8891#><#61943#> and <#61944#><#8892#>false<#8892#><#61944#> otherwise. We can translate both parts into equations. The first one,
<#8897#>(c?<#8897#> <#8898#>(make-c<#8898#> <#8899#>V-1<#8899#> <#8900#>...<#8900#> <#8901#>V-n))<#8901#> <#8902#>=<#8902#> <#8903#>true<#8903#> <#8904#>,<#8904#> 
relates <#61945#><#8908#>c?<#8908#><#61945#> and values constructed with <#61946#><#8909#>make-c<#8909#><#61946#>; the second one,
<#8914#>(c?<#8914#> <#8915#>V)<#8915#> <#8916#>=<#8916#> <#8917#>false<#8917#><#70917#>; if <#61947#><#8918#>V<#8918#><#61947#> is a value not constructed with <#61948#><#8919#>make-c<#8919#><#61948#> , <#70917#>
relates <#61949#><#8923#>c?<#8923#><#61949#> to all other values. Again, the equations are best understood in terms of our example. Here are the general equations:
<#8928#>(point?<#8928#> <#8929#>(make-point<#8929#> <#8930#>V<#8930#> <#8931#>U<#8931#> <#8932#>W))<#8932#> <#8933#>=<#8933#> <#8934#>true<#8934#>
<#8935#>(point?<#8935#> <#8936#>U)<#8936#> <#8937#>=<#8937#> <#8938#>false<#8938#> <#70918#>; if <#61950#><#8939#>U<#8939#><#61950#> is value, but not a <#61951#><#8940#>point<#8940#><#61951#> structure.<#70918#> 
Thus, <#61952#><#8944#>(point?<#8944#>\ <#8945#>(make-point<#8945#>\ <#8946#>3<#8946#>\ <#8947#>4<#8947#>\ <#8948#>5))<#8948#><#61952#> is <#61953#><#8949#>true<#8949#><#61953#> and <#61954#><#8950#>(point?<#8950#>\ <#8951#>3)<#8951#><#61954#> is <#61955#><#8952#>false<#8952#><#61955#>.
<#8955#>Exercise 8.7.1<#8955#> Distinguish legal from illegal sentences:
  1. <#61956#><#8958#>(define-struct<#8958#>\ <#8959#>personnel-record<#8959#>\ <#8960#>(name<#8960#>\ <#8961#>salary<#8961#>\ <#8962#>dob<#8962#>\ <#8963#>ssn))<#8963#><#61956#>
  2. <#61957#><#8964#>(define-struct<#8964#>\ <#8965#>oops<#8965#>\ <#8966#>())<#8966#><#61957#>
  3. <#61958#><#8967#>(define-struct<#8967#>\ <#8968#>child<#8968#>\ <#8969#>(dob<#8969#>\ <#8970#>date<#8970#>\ <#8971#>(-<#8971#>\ <#8972#>date<#8972#>\ <#8973#>dob)))<#8973#><#61958#>
  4. <#61959#><#8974#>(define-struct<#8974#>\ <#8975#>(child<#8975#>\ <#8976#>person)<#8976#>\ <#8977#>(dob<#8977#>\ <#8978#>date))<#8978#><#61959#>
  5. <#61960#><#8979#>(define-struct<#8979#>\ <#8980#>child<#8980#>\ <#8981#>(parents<#8981#>\ <#8982#>dob<#8982#>\ <#8983#>date))<#8983#><#61960#>
Explain why the sentences are legal <#61961#><#8985#>define-struct<#8985#><#61961#> definitions or how they fail to be legal <#61962#><#8986#>define-struct<#8986#><#61962#> definitions.~ external Solution<#61963#><#61963#> <#8992#>Exercise 8.7.2<#8992#> Which of the following are values and which are just applications of <#61964#><#8994#>make-point<#8994#><#61964#> to expressions?
  1. <#61965#><#8996#>(make-point<#8996#>\ <#8997#>1<#8997#>\ <#8998#>2<#8998#>\ <#8999#>3)<#8999#><#61965#>
  2. <#61966#><#9000#>(make-point<#9000#>\ <#9001#>(make-point<#9001#>\ <#9002#>1<#9002#>\ <#9003#>2<#9003#>\ <#9004#>3)<#9004#>\ <#9005#>4<#9005#>\ <#9006#>5)<#9006#><#61966#>
  3. <#61967#><#9007#>(make-point<#9007#>\ <#9008#>(+<#9008#>\ <#9009#>1<#9009#>\ <#9010#>2)<#9010#>\ <#9011#>3<#9011#>\ <#9012#>4)<#9012#><#61967#>~ external Solution<#61968#><#61968#>
<#9019#>Exercise 8.7.3<#9019#> Suppose the <#9022#>Definitions<#9022#> window contains
<#9027#>(define-struct<#9027#> <#9028#>ball<#9028#> <#9029#>(x<#9029#> <#9030#>y<#9030#> <#9031#>speed-x<#9031#> <#9032#>speed-y))<#9032#>
Determine the results of the following expressions:
  1. <#61969#><#9037#>(number?<#9037#>\ <#9038#>(make-ball<#9038#>\ <#9039#>1<#9039#>\ <#9040#>2<#9040#>\ <#9041#>3<#9041#>\ <#9042#>4))<#9042#><#61969#>
  2. <#61970#><#9043#>(ball-speed-y<#9043#>\ <#9044#>(make-ball<#9044#>\ <#9045#>(+<#9045#>\ <#9046#>1<#9046#>\ <#9047#>2)<#9047#>\ <#9048#>(+<#9048#>\ <#9049#>3<#9049#>\ <#9050#>3)<#9050#>\ <#9051#>2<#9051#>\ <#9052#>3))<#9052#><#61970#>
  3. <#61971#><#9053#>(ball-y<#9053#>\ <#9054#>(make-ball<#9054#>\ <#9055#>(+<#9055#>\ <#9056#>1<#9056#>\ <#9057#>2)<#9057#>\ <#9058#>(+<#9058#>\ <#9059#>3<#9059#>\ <#9060#>3)<#9060#>\ <#9061#>2<#9061#>\ <#9062#>3))<#9062#><#61971#>
Also check how DrScheme deals with the following expressions:
  1. <#61972#><#9065#>(number?<#9065#>\ <#9066#>(make-ball<#9066#>\ <#9067#>1<#9067#>\ <#9068#>3<#9068#>\ <#9069#>4))<#9069#><#61972#>
  2. <#61973#><#9070#>(ball-x<#9070#>\ <#9071#>(make-posn<#9071#>\ <#9072#>1<#9072#>\ <#9073#>2))<#9073#><#61973#>
  3. <#61974#><#9074#>(ball-speed-y<#9074#>\ <#9075#>5)<#9075#><#61974#>
Verify your solutions with DrScheme.~ external Solution<#61975#><#61975#>

#tabular9083#

<#62007#>Figure: <#9127#>Scheme Beginning Student<#9127#>: The full grammar<#62007#>