The Need for Memory

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.