Programs need memory because we want them to work with users who know
little or nothing about programming. Even if we wanted users to employ
DrScheme's <#45081#>Interactions<#45081#> window, we would organize our programs so
that each service corresponds to a function and the function collaborate
through memory. With graphical user interfaces, we are almost forced to
think of programs as a collection of collaborating functions attached to
various widgets in a window. Finally, even programs that work in physical
devices such as elevators or VCRs are forced to interact with the device in
some fixed way, and that often includes keeping around information about
the history of device-program interactions. In short, the interface between
the program and the rest of the world dictates whether a program needs
memory and what kind of memory it needs.
Fortunately it is relatively easy to recognize when programs truly need
memory. As discussed already, there are two situations. The first involves
programs that provide more than one service to users. Each service
corresponds to a function. A user may apply these functions in DrScheme's
<#45082#>Interaction<#45082#> window, or they may be applied in response to some
user action in a graphical user interface. The second involves a program
that provides a single service and is implemented with a single user-level
function. But the program may have to produce different answers when it is
applied to the same arguments.
Let us take a look at some concrete examples for each situation. Software
for managing an address book is a classical example of the first kind. In
sections~#secmemory#45083> and~#secsetbang#45084>, we saw how one function
adds entries to the address book, and another one looks them up. Clearly,
the use of the ``addition service'' affects future uses of the ``lookup
service'' and therefore requires memory. Indeed, the memory in this case
corresponds to a natural physical object: the address book that people used
to keep in place of electronic notebooks.
Next, consider a warehouse with a clerk that registers the items that
people deliver and pick up. Every time someone delivers an item, the clerk
enters it into a ledger; an inquiry for a specific item triggers a search
in the ledger; when someone picks up an item, the clerk removes it from the
ledger. If we were to provide a function for managing the ledger, the
program would have to offer three services: one for entering items, one for
searching in the ledger, and one for removing entries from the ledger. Of
course, we can't remove something that isn't in the warehouse, so the
program must ensure that the two services interact properly. The memory in
this program will be similar to the ledgers that warehouse clerks use (or
used), that is, a physical object.
The second class of memory need also has its classical examples. The
traffic light simulation mentioned in section~#secmemory#45085> is one of
them. Recall that the description of the program <#68161#><#45086#>next<#45086#><#68161#> says that
every time it is applied, it redraws the picture on a canvas according to
the common traffic rules. Because two evaluations of <#68162#><#45087#>(next)<#45087#><#68162#> in a
row produce two different effects, this program needs memory.
For another example, take a look at the Scheme function <#68163#><#45088#>random<#45088#><#68163#>.
It consumes a natural number n and produces a number between 0 and
n-1. If we evaluate <#68164#><#45089#>(random<#45089#>\ <#45090#>10)<#45090#><#68164#> twice in a row, we may or may
not obtain the same digit. Again, to achieve this effect, the implementor
of <#68165#><#45091#>random<#45091#><#68165#> needed to equip the function with some memory.
<#45138#>Figure: Organizational charts for programs with memory<#45138#>
In general, as we analyze a problem statement, we should draw organization
charts. Figure~#figsetchart#45140> contains sample charts for the
phone-book and the traffic-light programs. They represent each service that
the program is to support with a rectangular box. Arrows going into the
box indicate what kind of data a service consumes; outgoing arrows specify
the output. Memory is represented with circles. An arrow from a circle to a
box means that the service uses the memory as an input; an arrow to a
circle means that the service changes the memory. The two charts show that
services commonly use memory and change it.