Structures

Suppose we wish to represent the <#3712#>pixels<#3712#> (colored dots) on our computer monitors. A pixel is very much like a Cartesian point. It has a x-coordinate, which tells us where the pixel is in the horizontal direction, and it has a y-coordinate, which tells us where the pixel is located in the downwards vertical direction. Given the two numbers, we can locate a pixel on the monitor, and so can a computer program. DrScheme's teachpacks represent pixels with <#60945#><#3713#>posn<#3713#><#60945#> structures. A <#60946#><#3714#>posn<#3714#><#60946#> structure combines two numbers. That is, a <#60947#><#3715#>posn<#3715#><#60947#> is a single value that contains two values. We can create a <#60948#><#3716#>posn<#3716#><#60948#> structure with the operation <#60949#><#3717#>make-posn<#3717#><#60949#>, which consumes two numbers and makes a <#60950#><#3718#>posn<#3718#><#60950#>. For example,
<#3723#>(make-posn<#3723#> <#3724#>3<#3724#> <#3725#>4)<#3725#>
<#3726#>(make-posn<#3726#> <#3727#>8<#3727#> <#3728#>6)<#3728#> 
<#3729#>(make-posn<#3729#> <#3730#>5<#3730#> <#3731#>12)<#3731#> 
are <#60951#><#3735#>posn<#3735#><#60951#> structures. Each of these structures has the same status as a number as far as computations are concerned. Both primitive operations and functions can consume and produce structures. Now consider a function that computes how far some pixel is from the origin. The contract, header, and purpose statement are easy to formulate:
<#70732#>;; <#60952#><#3740#>distance-to-0<#3740#> <#3741#>:<#3741#> <#3742#>posn<#3742#> <#3743#><#3743#><#3744#>-;SPMgt;<#3744#><#3745#><#3745#> <#3746#>number<#3746#><#60952#><#70732#>
<#70733#>;; to compute the distance of <#60953#><#3747#>a-posn<#3747#><#60953#> to the origin <#70733#> 
<#3748#>(define<#3748#> <#3749#>(distance-to-0<#3749#> <#3750#>a-posn)<#3750#> <#3751#>...)<#3751#> 
In other words, <#60954#><#3755#>distance-to-0<#3755#><#60954#> consumes a single value, a <#60955#><#3756#>posn<#3756#><#60955#> structure, and produces a single value, a number. We already have some input examples, namely the three <#60956#><#3757#>posn<#3757#><#60956#> structures mentioned above. What we need next are examples that relate inputs and outputs. For points with <#60957#><#3758#>0<#3758#><#60957#> as one of the coordinates, the result is the other coordinate:
  <#3763#>(distance-to-0<#3763#> <#3764#>(make-posn<#3764#> <#3765#>0<#3765#> <#3766#>5))<#3766#>
<#3767#>=<#3767#> <#3768#>5<#3768#> 
<#3769#>;and<#3769#> 
  <#3770#>(distance-to-0<#3770#> <#3771#>(make-posn<#3771#> <#3772#>7<#3772#> <#3773#>0))<#3773#> 
<#3774#>=<#3774#> <#3775#>7<#3775#> 
In general, we know from geometry that the distance from the origin to a position with coordinates <#60958#><#3779#>x<#3779#><#60958#> and <#60959#><#3780#>y<#3780#><#60959#> is distance

#displaymath72736#

Thus,

  <#3786#>(distance-to-0<#3786#> <#3787#>(make-posn<#3787#> <#3788#>3<#3788#> <#3789#>4))<#3789#>
<#3790#>=<#3790#> <#3791#>5<#3791#> 
  <#3792#>(distance-to-0<#3792#> <#3793#>(make-posn<#3793#> <#3794#>8<#3794#> <#3795#>6))<#3795#> 
<#3796#>=<#3796#> <#3797#>10<#3797#> 
  <#3798#>(distance-to-0<#3798#> <#3799#>(make-posn<#3799#> <#3800#>5<#3800#> <#3801#>12))<#3801#> 
<#3802#>=<#3802#> <#3803#>13<#3803#>  
Once we have examples, we can turn our attention to the definition of the function. The examples imply that the design of <#60960#><#3807#>distance-to-0<#3807#><#60960#> doesn't need to distinguish between different situations. Still, we are stuck now, because <#60961#><#3808#>distance-to-0<#3808#><#60961#> has a single parameter that represents the entire pixel but we need the two coordinates to compute the distance. Put differently, we know how to combine two numbers into a <#60962#><#3809#>posn<#3809#><#60962#> structure using <#60963#><#3810#>make-posn<#3810#><#60963#> and we don't know how to extract these numbers from a <#60964#><#3811#>posn<#3811#><#60964#> structure. Scheme provides operations for extracting values from structures. For <#60965#><#3813#>posn<#3813#><#60965#> structures, Scheme supports two such operations: <#60966#><#3814#>posn-x<#3814#><#60966#> and <#60967#><#3815#>posn-y<#3815#><#60967#>. The former operation extracts the x-coordinate; the latter extracts the y-coordinate. To describe how <#60968#><#3816#>posn-x<#3816#><#60968#>, <#60969#><#3817#>posn-y<#3817#><#60969#>, and <#60970#><#3818#>make-posn<#3818#><#60970#> are related, we can use equations that are roughly analogous to the equations that govern addition and subtraction:
  <#3823#>(posn-x<#3823#> <#3824#>(make-posn<#3824#> <#3825#>7<#3825#> <#3826#>0))<#3826#> 
<#3827#>=<#3827#> <#3828#>7<#3828#> 
and
  <#3836#>(posn-y<#3836#> <#3837#>(make-posn<#3837#> <#3838#>7<#3838#> <#3839#>0))<#3839#>
<#3840#>=<#3840#> <#3841#>0<#3841#> 
The equations only confirm what we already know. But suppose we introduce the following definition:
  <#3849#>(define<#3849#> <#3850#>a-posn<#3850#> <#3851#>(make-posn<#3851#> <#3852#>7<#3852#> <#3853#>0))<#3853#>
Then we can use the two operations as follows in the <#3857#>Interactions<#3857#> window:
  <#3862#>(posn-x<#3862#> <#3863#>a-posn)<#3863#> 
<#3864#>=<#3864#> <#3865#>7<#3865#> 
  <#3866#>(posn-y<#3866#> <#3867#>a-posn)<#3867#> 
<#3868#>=<#3868#> <#3869#>0<#3869#> 
Naturally, we can nest such expressions:
  <#3877#>(*<#3877#> <#3878#>(posn-x<#3878#> <#3879#>a-posn)<#3879#> <#3880#>7)<#3880#>
<#3881#>=<#3881#> <#3882#>49<#3882#> 
  <#3883#>(+<#3883#> <#3884#>(posn-y<#3884#> <#3885#>a-posn)<#3885#> <#3886#>13)<#3886#> 
<#3887#>=<#3887#> <#3888#>13<#3888#> 
Now we know enough to complete the definition of <#60971#><#3892#>distance-to-0<#3892#><#60971#>. We know that the function's <#60972#><#3893#>a-posn<#3893#><#60972#> parameter is a <#60973#><#3894#>posn<#3894#><#60973#> structure and that the structure contains two numbers which we can extract with <#60974#><#3895#>(posn-x<#3895#>\ <#3896#>a-posn)<#3896#><#60974#> and <#60975#><#3897#>(posn-y<#3897#>\ <#3898#>a-posn)<#3898#><#60975#>. Let us add this knowledge to our function outline:
<#3903#>(d<#3903#><#3904#>efine<#3904#> <#3905#>(distance-to-0<#3905#> <#3906#>a-posn)<#3906#>
  <#3907#>...<#3907#> <#3908#>(posn-x<#3908#> <#3909#>a-posn)<#3909#> <#3910#>...<#3910#> 
  <#3911#>...<#3911#> <#3912#>(posn-y<#3912#> <#3913#>a-posn)<#3913#> <#3914#>...)<#3914#> 
Using this outline and the examples, the rest is easy:
<#3922#>(d<#3922#><#3923#>efine<#3923#> <#3924#>(distance-to-0<#3924#> <#3925#>a-posn)<#3925#>
  <#3926#>(s<#3926#><#3927#>qrt<#3927#> 
    <#3928#>(+<#3928#> <#3929#>(square<#3929#> <#3930#>(posn-x<#3930#> <#3931#>a-posn))<#3931#> 
       <#3932#>(square<#3932#> <#3933#>(posn-y<#3933#> <#3934#>a-posn)))))<#3934#> 
The function squares <#60976#><#3938#>(posn-x<#3938#>\ <#3939#>a-posn)<#3939#><#60976#> and <#60977#><#3940#>(posn-y<#3940#>\ <#3941#>a-posn)<#3941#><#60977#>, which represent the <#3942#>x<#3942#> and <#3943#>y<#3943#> coordinates, sums up the results, and takes the square root. With DrScheme, we can also quickly check that our new function produces the proper results for our examples.
<#3946#>Exercise 6.1.1<#3946#> Evaluate the following expressions:
  1. <#60978#><#3949#>(distance-to-0<#3949#>\ <#3950#>(make-posn<#3950#>\ <#3951#>3<#3951#>\ <#3952#>4))<#3952#><#60978#>
  2. <#60979#><#3953#>(distance-to-0<#3953#>\ <#3954#>(make-posn<#3954#>\ <#3955#>(*<#3955#>\ <#3956#>2<#3956#>\ <#3957#>3)<#3957#>\ <#3958#>(*<#3958#>\ <#3959#>2<#3959#>\ <#3960#>4)))<#3960#><#60979#>
  3. <#60980#><#3961#>(distance-to-0<#3961#>\ <#3962#>(make-posn<#3962#>\ <#3963#>12<#3963#>\ <#3964#>(-<#3964#>\ <#3965#>6<#3965#>\ <#3966#>1)))<#3966#><#60980#>
by hand. Show all steps. Assume that <#60981#><#3968#>square<#3968#><#60981#> performs its computation in a single step. Check the results with DrScheme's stepper.~ external Solution<#60982#><#60982#>