Composing Functions, Revisited

As we analyze a problem statement, we might wish develop the data representation in stages. This is especially true when the problem statement mentions several different kinds of objects. It is easier to understand several smaller data definitions than one larger one. Let's return to our shape problem again. Instead of the class of shapes in a single data definition, we could start with two data definitions, one for each basic shape:
A <#61569#><#6756#>circle<#6756#><#61569#> is a structure:

<#70811#><#61570#><#6757#>(make-circle<#6757#>\ <#6758#>p<#6758#>\ <#6759#>s)<#6759#><#61570#><#70811#> where <#61571#><#6760#>p<#6760#><#61571#> is a <#61572#><#6761#>posn<#6761#><#61572#> and <#61573#><#6762#>s<#6762#><#61573#> is a number.

A <#61574#><#6765#>square<#6765#><#61574#> is a structure:

<#70812#><#61575#><#6766#>(make-square<#6766#>\ <#6767#>p<#6767#>\ <#6768#>s)<#6768#><#61575#><#70812#> where <#61576#><#6769#>p<#6769#><#61576#> is a <#61577#><#6770#>posn<#6770#><#61577#> and <#61578#><#6771#>s<#6771#><#61578#> is a number.

Both assume the structure definitions of section~#secmixeddatapred#6773>. Once we have developed and understood the basic data definitions, possibly by playing with examples and by writing simple functions, we can introduce data definitions that combine them. For example, we can introduce a data definition for a class of shapes that refers to the two above:
A <#61579#><#6775#>shape<#6775#><#61579#> is either
  1. a <#61580#><#6777#>circle<#6777#><#61580#>, or
  2. a <#61581#><#6778#>square<#6778#><#61581#>.
Now suppose we need to develop a function that consumes <#61582#><#6781#>shape<#6781#><#61582#>s. For the first step, we form a <#61583#><#6782#>cond<#6782#>-expression<#61583#> with conditions for each part of the data definition:
<#70813#>;; <#61584#><#6787#>f<#6787#> <#6788#>:<#6788#> <#6789#>shape<#6789#> <#6790#><#6790#><#6791#>-;SPMgt;<#6791#><#6792#><#6792#> <#6793#>?<#6793#><#6794#>?<#6794#><#6795#>?<#6795#><#61584#><#70813#>
<#6796#>(d<#6796#><#6797#>efine<#6797#> <#6798#>(f<#6798#> <#6799#>a-shape)<#6799#> 
  <#6800#>(c<#6800#><#6801#>ond<#6801#> 
    <#6802#>[<#6802#><#6803#>(circle?<#6803#> <#6804#>a-shape)<#6804#> <#6805#>...]<#6805#> 
    <#6806#>[<#6806#><#6807#>(square?<#6807#> <#6808#>a-shape)<#6808#> <#6809#>...]<#6809#><#6810#>))<#6810#> 
Given our guideline concerning the composition of functions (see section~#secbasicscompose#6814>) and given that the data definition refers to two other data definitions, the natural second step is to pass the argument to auxiliary functions:
<#70814#>;; <#61585#><#6819#>f<#6819#> <#6820#>:<#6820#> <#6821#>shape<#6821#> <#6822#><#6822#><#6823#>-;SPMgt;<#6823#><#6824#><#6824#> <#6825#>?<#6825#><#6826#>?<#6826#><#6827#>?<#6827#><#61585#><#70814#>
<#6828#>(d<#6828#><#6829#>efine<#6829#> <#6830#>(f<#6830#> <#6831#>a-shape)<#6831#> 
  <#6832#>(c<#6832#><#6833#>ond<#6833#> 
    <#6834#>[<#6834#><#6835#>(circle?<#6835#> <#6836#>a-shape)<#6836#> <#6837#>(f-for-circle<#6837#> <#6838#>a-shape)]<#6838#> 
    <#6839#>[<#6839#><#6840#>(square?<#6840#> <#6841#>a-shape)<#6841#> <#6842#>(f-for-square<#6842#> <#6843#>a-shape)]<#6843#><#6844#>))<#6844#> 
This, in turn, requires that we develop the two auxiliary functions, <#61586#><#6848#>f-for-circle<#6848#><#61586#> and <#61587#><#6849#>f-for-square<#6849#><#61587#>, including their templates.
<#61588#>;; <#6856#>Data Definition<#6856#>:<#61588#>
<#6857#>(define-struct<#6857#> <#6858#>circle<#6858#> <#6859#>(center<#6859#> <#6860#>radius))<#6860#> 
<#6861#>(define-struct<#6861#> <#6862#>square<#6862#> <#6863#>(nw<#6863#> <#6864#>length<#6864#><#6865#>))<#6865#> 
<#70815#>;; A <#61589#><#6866#>shape<#6866#><#61589#> is either<#70815#> 
<#70816#>;; 1. a structure: <#61590#><#6867#>(make-circle<#6867#> <#6868#>p<#6868#> <#6869#>s)<#6869#><#61590#><#70816#> 
<#70817#>;; ~~ where <#61591#><#6870#>p<#6870#><#61591#> is a <#61592#><#6871#>posn<#6871#><#61592#>, <#61593#><#6872#>s<#6872#><#61593#> a number;<#70817#> 
<#70818#>;; 2. a structure: <#61594#><#6873#>(make-square<#6873#> <#6874#>p<#6874#> <#6875#>s)<#6875#><#61594#><#70818#> 
<#70819#>;; ~~ where <#61595#><#6876#>p<#6876#><#61595#> is a <#61596#><#6877#>posn<#6877#><#61596#>, <#61597#><#6878#>s<#6878#><#61597#> a number.<#70819#> 






~~~~~~~~~~
<#61598#>;; <#6889#>Data Definitions<#6889#>:<#61598#>
<#6890#>(define-struct<#6890#> <#6891#>circle<#6891#> <#6892#>(center<#6892#> <#6893#>radius))<#6893#> 
<#70820#>;; A <#61599#><#6894#>circle<#6894#><#61599#> is a structure:<#70820#> 
<#70821#>;; <#61600#><#6895#>(make-circle<#6895#> <#6896#>p<#6896#> <#6897#>s)<#6897#><#61600#><#70821#> 
<#70822#>;; ~~ where <#61601#><#6898#>p<#6898#><#61601#> is a <#61602#><#6899#>posn<#6899#><#61602#>, <#61603#><#6900#>s<#6900#><#61603#> a number;<#70822#> 

<#6901#>(define-struct<#6901#> <#6902#>square<#6902#> <#6903#>(nw<#6903#> <#6904#>length<#6904#><#6905#>))<#6905#> 
<#70823#>;; A <#61604#><#6906#>square<#6906#><#61604#> is a structure:<#70823#> 
<#70824#>;; <#61605#><#6907#>(make-square<#6907#> <#6908#>p<#6908#> <#6909#>s)<#6909#><#61605#><#70824#> 
<#70825#>;; ~~ where <#61606#><#6910#>p<#6910#><#61606#> is a <#61607#><#6911#>posn<#6911#><#61607#>, <#61608#><#6912#>s<#6912#><#61608#> a number.<#70825#> 

<#70826#>;; A <#61609#><#6913#>shape<#6913#><#61609#> is either<#70826#> 
<#6914#>;; 1. a circle, or<#6914#> 
<#6915#>;; 2. a structure. <#6915#> 

<#61610#>;; <#6924#>Final Definition<#6924#>: <#61610#>
<#70827#>;; <#61611#><#6925#>perimeter<#6925#> <#6926#>:<#6926#> <#6927#>shape<#6927#> <#6928#><#6928#><#6929#>-;SPMgt;<#6929#><#6930#><#6930#> <#6931#>number<#6931#><#61611#><#70827#> 
<#70828#>;; to compute the perimeter of <#61612#><#6932#>a-shape<#6932#><#61612#><#70828#> 
<#6933#>(d<#6933#><#6934#>efine<#6934#> <#6935#>(perimeter<#6935#> <#6936#>a-shape)<#6936#> 
  <#6937#>(c<#6937#><#6938#>ond<#6938#> 
    <#6939#>[<#6939#><#6940#>(circle?<#6940#> <#6941#>a-shape)<#6941#> 
     <#6942#>(*<#6942#> <#6943#>(*<#6943#> <#6944#>2<#6944#> <#6945#>(circle-radius<#6945#> <#6946#>a-shape))<#6946#> <#6947#>pi)]<#6947#> 
    <#6948#>[<#6948#><#6949#>(square?<#6949#> <#6950#>a-shape)<#6950#> 
     <#6951#>(*<#6951#> <#6952#>(square-length<#6952#> <#6953#>a-shape)<#6953#> <#6954#>4)]<#6954#><#6955#>))<#6955#> 










~~~~~~~~~~
<#61613#>;; <#6966#>Final Definitions<#6966#>: <#61613#>
<#70829#>;; <#61614#><#6967#>perimeter<#6967#> <#6968#>:<#6968#> <#6969#>shape<#6969#> <#6970#><#6970#><#6971#>-;SPMgt;<#6971#><#6972#><#6972#> <#6973#>number<#6973#><#61614#><#70829#> 
<#70830#>;; to compute the perimeter of <#61615#><#6974#>a-shape<#6974#><#61615#><#70830#> 
<#6975#>(d<#6975#><#6976#>efine<#6976#> <#6977#>(perimeter<#6977#> <#6978#>a-shape)<#6978#> 
  <#6979#>(c<#6979#><#6980#>ond<#6980#> 
    <#6981#>[<#6981#><#6982#>(circle?<#6982#> <#6983#>a-shape)<#6983#> 
     <#6984#>(perimeter-circle<#6984#> <#6985#>a-shape)]<#6985#> 
    <#6986#>[<#6986#><#6987#>(square?<#6987#> <#6988#>a-shape)<#6988#> 
     <#6989#>(perimeter-square<#6989#> <#6990#>a-shape)]<#6990#><#6991#>))<#6991#> 

<#70831#>;; <#61616#><#6992#>perimeter-circle<#6992#> <#6993#>:<#6993#> <#6994#>circle<#6994#> <#6995#><#6995#><#6996#>-;SPMgt;<#6996#><#6997#><#6997#> <#6998#>number<#6998#><#61616#><#70831#> 
<#70832#>;; to compute the perimeter of <#61617#><#6999#>a-circle<#6999#><#61617#><#70832#> 
<#7000#>(d<#7000#><#7001#>efine<#7001#> <#7002#>(perimeter-circle<#7002#> <#7003#>a-circle)<#7003#> 
  <#7004#>(*<#7004#> <#7005#>(*<#7005#> <#7006#>2<#7006#> <#7007#>(circle-length<#7007#> <#7008#>a-circle))<#7008#> <#7009#>pi))<#7009#> 

<#70833#>;; <#61618#><#7010#>perimeter-square<#7010#> <#7011#>:<#7011#> <#7012#>square<#7012#> <#7013#><#7013#><#7014#>-;SPMgt;<#7014#><#7015#><#7015#> <#7016#>number<#7016#><#61618#><#70833#> 
<#70834#>;; to compute the perimeter of <#61619#><#7017#>a-square<#7017#><#61619#><#70834#> 
<#7018#>(d<#7018#><#7019#>efine<#7019#> <#7020#>(perimeter-square<#7020#> <#7021#>a-square)<#7021#> 
  <#7022#>(*<#7022#> <#7023#>(square-length<#7023#> <#7024#>a-square)<#7024#> <#7025#>4))<#7025#> 
<#61620#>Figure: Two ways to define <#7030#>perimeter<#7030#><#61620#>
If we follow this suggestion, we arrive at a collection of three functions, one per data definition. The essential points of the program development are summarized in the right column of figure~#figcomparetemplate#7032>. For a comparison, the left column contains the corresponding pieces of the original program development. In each case, we have as many functions as there are data definitions. Furthermore, the references between the functions in the right column directly match to the references among the corresponding data definitions. While this symmetry between data definitions and functions may seem trivial now, it becomes more and more important as we study more complex ways of defining data.
<#7035#>Exercise 7.3.1<#7035#> Modify the two versions of <#61621#><#7037#>perimeter<#7037#><#61621#> so that they also process rectangles. For our purposes, the description of a rectangle includes its upper-left corner, its width, and its height. ~ external Solution<#61622#><#61622#>