Memory is implemented with variable definitions. The memory-using programs
we have seen used a single variable to represent the memory of a
function. In principle, a single variable is enough to implement all memory
needs, but this is usually inconvenient. Typically, the memory analysis
suggests how many variables we need and which services need which
variables. When memory changes, the corresponding variables assume a new
value or, put differently, the state of the variable declaration changes
and reflects the memory change over time. We therefore refer to variables
that implement memory as <#68196#><#45143#>STATE VARIABLES<#45143#><#68196#>.
Every service in a program corresponds to a function that may employ
auxiliary functions. A service that changes the memory of a program is
implemented with a function that uses <#68197#><#45144#>set!<#45144#><#68197#> on some of the state
variables. To understand how a function should change a state variable, we
need to know what kind of values the variable may represent and what its
purpose is. In other words, we must develop a contract and a purpose
statement for state variables in the same manner in which we develop
contracts and purpose statements for function definitions.
Let us take a look at the address-book and the traffic-light examples. The
first one has one state variable: <#68198#><#45145#>address-book<#45145#><#68198#>. It is intended to
represent a list of entries, where each entry is a list of two items: a
name and a number. To document that <#68199#><#45146#>address-book<#45146#><#68199#> may only
represent such lists, we add a contract as follows:
<#71712#>;; <#68200#><#45151#>address-book<#45151#> <#45152#>:<#45152#> <#45153#>(listof<#45153#> <#45154#>(list<#45154#> <#45155#>symbol<#45155#> <#45156#>number))<#45156#><#68200#><#71712#>
<#45157#>;; to keep track of pairs of names and phone numbers<#45157#>
<#45158#>(define<#45158#> <#45159#>address-book<#45159#> <#45160#>empty)<#45160#>
Recall that <#68201#><#45164#>(listof<#45164#>\ <#45165#>X)<#45165#><#68201#> and <#68202#><#45166#>(list<#45166#>\ <#45167#>Y<#45167#>\ <#45168#>Z)<#45168#><#68202#> are short-hands for
data definitions. By the definition of <#68203#><#45169#>(listof<#45169#>\ <#45170#>X)<#45170#><#68203#>, it is
permissible to use <#68204#><#45171#>empty<#45171#><#68204#> as the initial value of
<#68205#><#45172#>address-book<#45172#><#68205#>.
From the contract for the state variable, we can conclude that the following
assignment is nonsensical:
<#45177#>(set!<#45177#> <#45178#>address-book<#45178#> <#45179#>5)<#45179#>
It sets <#68206#><#45183#>address-book<#45183#><#68206#> to <#68207#><#45184#>5<#45184#><#68207#>, which is not a list. The
expression therefore violates the state variable's contract. But
<#45189#>(set!<#45189#> <#45190#>address-book<#45190#> <#45191#>empty)<#45191#>
is proper, because it sets <#68208#><#45195#>address-book<#45195#><#68208#> back to its initial
value. Here is a third assignment:
<#45200#>(set!<#45200#> <#45201#>address-book<#45201#> <#45202#>(cons<#45202#> <#45203#>(list<#45203#> <#45204#>'<#45204#><#45205#>Adam<#45205#> <#45206#>1)<#45206#> <#45207#>address-book))<#45207#>
It helps us gain some understanding how functions can change the value of
<#68209#><#45211#>address-book<#45211#><#68209#> in a useful manner. Because <#68210#><#45212#>address-book<#45212#><#68210#>
stands for a list of lists, <#68211#><#45213#>(cons<#45213#>\ <#45214#>(list<#45214#>\ <#45215#>'<#45215#><#45216#>Adam<#45216#>\ <#45217#>1)<#45217#>\ <#45218#>address-book)<#45218#><#68211#>
constructs a longer list of the right kind. Hence, the <#68212#><#45219#>set!<#45219#><#68212#>
expression just changes the state variable to stand for a different value in
the class of <#68213#><#45220#>(listof<#45220#>\ <#45221#>(list<#45221#>\ <#45222#>symbol<#45222#>\ <#45223#>number))<#45223#><#68213#>.
A program that controls a traffic light should contain a variable
definition for the current color of the traffic light. This variable should
assume one of three values: <#68214#><#45224#>'<#45224#><#45225#>red<#45225#><#68214#>, <#68215#><#45226#>'<#45226#><#45227#>green<#45227#><#68215#>, or
<#68216#><#45228#>'<#45228#><#45229#>yellow<#45229#><#68216#>, which suggests a data definition:
A <#68217#><#45231#>TL-color<#45231#><#68217#> is either <#68218#><#45232#>'<#45232#><#45233#>green<#45233#><#68218#>, <#68219#><#45234#>'<#45234#><#45235#>yellow<#45235#><#68219#>, or <#68220#><#45236#>'<#45236#><#45237#>red<#45237#><#68220#>.
Here is the variable definition with matching contract
and purpose statement:
<#71713#>;; <#68221#><#45243#>current-color<#45243#> <#45244#>:<#45244#> <#45245#>TL-color<#45245#><#68221#><#71713#>
<#45246#>;; to keep track of the current color of the traffic light<#45246#>
<#45247#>(define<#45247#> <#45248#>current-color<#45248#> <#45249#>'<#45249#><#45250#>red)<#45250#>
As before, the expression
<#45258#>(set!<#45258#> <#45259#>current-color<#45259#> <#45260#>5)<#45260#>
is nonsensical because <#68222#><#45264#>5<#45264#><#68222#> is not one of the three legitimate
symbols mentioned in the contract. In contrast,
<#45269#>(set!<#45269#> <#45270#>current-color<#45270#> <#45271#>'<#45271#><#45272#>green)<#45272#>
is perfectly okay.
The right-hand side of an assignment does not have to consist of a value or
an expression that almost instantaneously produces a value. In many cases
it makes sense to use a function to compute the new value. Here is a
function that computes the next color for our traffic light:
<#71714#>;; <#68223#><#45281#>next-color<#45281#> <#45282#>:<#45282#> <#45283#>TL-color<#45283#> <#45284#><#45284#><#45285#>-;SPMgt;<#45285#><#45286#><#45286#> <#45287#>TL-color<#45287#><#68223#><#71714#>
<#45288#>;; to compute the next color for a traffic light <#45288#>
<#45289#>(d<#45289#><#45290#>efine<#45290#> <#45291#>(next-color<#45291#> <#45292#>c)<#45292#>
<#45293#>(c<#45293#><#45294#>ond<#45294#>
<#45295#>[<#45295#><#45296#>(symbol=?<#45296#> <#45297#>'<#45297#><#45298#>red<#45298#> <#45299#>c)<#45299#> <#45300#>'<#45300#><#45301#>green]<#45301#>
<#45302#>[<#45302#><#45303#>(symbol=?<#45303#> <#45304#>'<#45304#><#45305#>green<#45305#> <#45306#>c)<#45306#> <#45307#>'<#45307#><#45308#>yellow]<#45308#>
<#45309#>[<#45309#><#45310#>(symbol=?<#45310#> <#45311#>'<#45311#><#45312#>yellow<#45312#> <#45313#>c)<#45313#> <#45314#>'<#45314#><#45315#>red]<#45315#><#45316#>))<#45316#>
Using this function, we can now write an assignment that switches the state
of <#68224#><#45320#>current-color<#45320#><#68224#> appropriately:
<#45325#>(set!<#45325#> <#45326#>current-color<#45326#> <#45327#>(next-color<#45327#> <#45328#>current-color))<#45328#>
Because <#68225#><#45332#>current-color<#45332#><#68225#> is one of the three legitimate symbols,
we can apply <#68226#><#45333#>next-color<#45333#><#68226#> to the value of <#68227#><#45334#>current-color<#45334#><#68227#>.
The function also produces one of these three symbols, so that the next
state of <#68228#><#45335#>current-color<#45335#><#68228#> is again proper.