• No results found

We now explain the semantics of a simple program to reverse a list, which illustrates most aspects of WHILE.

Example 2.1.4 Consider the following program,reverse: read X; Y := nil; while X do Y := cons (hd X) Y; X := tl X; write Y

The program consists of a read command, a body, and a write command. The idea is that some inputd ∈ID is assigned to the variableX, and then the body isexecuted. At any point during execution every variable is bound to an element of ID; the collection of all such bindings at one point is astore. InitiallyXis bound to the inputd∈ID, and all other variables in the program are bound to nil. If execution of the body terminates, the valuee∈ID last bound to Yis theoutput.

Forreverse, ifXis initially bound to input (d0.(d1.(· · ·.(dn−1.(dn.nil))· · ·)))

thenYis bound to

(dn.(dn−1.(· · ·.(d1.(d0.nil))· · ·)))

when execution reaches the final write command, and this later element of ID is then the output.

To bind a variable, sayY, to somef∈ID one uses the assignmentY:=f. So the second line assignsniltoY.3

More generally every expressionEevaluatesto somee∈ID, andZ := E assigns this etoZ. Specifically, E evaluates toe. As another example cons E Fevaluates to(e.f) if Eevaluates to eand F evaluates to f. Further, hd E and tl E evaluate toe and f, respectively, if E evaluates to (e.f). Finally, a variable Z evaluates to the value it is currently bound to.

3Since all variables are initially bound tonilthis command is superfluous. However it often happens

that one assigns somef∈ID to a variable without ever making use of the initial valuenil. Therefore, if onedoeswant to make use of the initial valuenil, it is good programming practice to enter an explicit assignmentY := nilin the program.

The expression=? E Fevaluates totrue, ifEandFevaluate to the same value, and to falseotherwise. Thus=? (nil.nil) (nil.nil)evaluates totrue, and=? (nil.nil) nilevaluates tofalse.

Turning to our program, the next thing that happens is that the while command beginning in the third line is executed. The meaning of the command while E do Cis as follows. IfEevaluates tonilproceed to the command followingwhile E do C. In the example this is the commandwrite Y. However, ifEevaluates to something other than nilexecuteC, and test again whetherEevaluates to nil. The outcome of this test may be different from the first since the variables occurring inEmay have been assigned new values by the commandC. IfEevaluates tonil, go to the next command, and otherwise executeCand test Eagain, etc.

So in the example program, the commands Y := cons (hd X) Y; X := tl X are executed in sequence as long as X is not bound to nil. Before the first of these two commandsXis bound to(e.d)(otherwise execution would have proceeded to the write command) andYis bound to somef. After the first commandYis bound to(e.f), and after the second commandXis bound to d.

If we think of the value (d0.(d1.(· · ·.(dn−1.(dn.nil)) · · ·))) as a list d0, d1, . . ., dn−1,dn, then the program reverses lists; more about lists in Subsection 2.1.5. 2

2.1.4

Truth values and if-then-else

As is apparent from the preceding example, whenever evaluating expressions in tests one should think ofnilas “false” and any other element of ID as “true.” This intuition is so predominant that we explicate it in a definition:

Definition 2.1.5 We use the following abbreviations: false = nil

true = (nil.nil)

Conditional commands and boolean expressions. We now see that conditional commands can be expressed bywhile-commands alone.

Example 2.1.6 The following compound command executesCif and only ifEevaluates totrue. VariableZmust be chosen different from existing variables.

Z := E; (* if E then C *) while Z do { Z := false; C };

The next statement will executeC1ifEevaluates totrue and otherwiseC2. Z := E; (* if E then C1 else C2 *)

W := true;

while Z do { Z := false; W := false; C1 }; while W do { W := false; C2 };

2

The same idea may be applied to expressions, rather than just commands, thus expressing conjunctionE and F, disjunctionE or F, or negationnot E, etc..

2.1.5

Lists

As one can see from the example in subsection 2.1.3, elements of ID sometimes have deeply nested parentheses that are hard to read; one has to resort to counting to parse an element like((a.(b.nil)).((d.(e.nil)).nil)).

Often the nesting has a certain regular structure, because we often express a list of elements d0, d1,. . . , dn−1, dn as the tree (d0.(d1.(· · ·.(dn−1.(dn.nil)) · · ·))). For

instance(a.(b.nil))represents the list consisting of elementsa,b. Therefore it would be particularly convenient to have a short notation for this form. Hence the idea is to use the notation(d0· · ·dn)for the tree(d0.(d1.(· · ·.(dn−1.(dn.nil))· · ·))). Then the

tree(a.(b.nil)) can be written(a b) in short notation and, as another example, the tree((a.(b.nil)).((d.(e.nil)).nil)can be written((a b) (d e)).

This is introduced in the following definition.

Definition 2.1.7 The list representation d of d∈ID is the string of symbols from al- phabet{nil,(, .,)} defined recursively as follows:

d=

(

d ifdis an atom

(d1· · ·dn) ifd=(d1.(d2.(· · ·(dn.nil) · · ·)))

We call(d1· · ·dn)alist of lengthl(d) =n; nilis the empty list of length 0. In general,

a length may be computed for any element of ID by induction: l(nil) = 0

l((d1.d2)) = 1 +l(d2)

2

Notice that every element of ID has exactly one list representation. Henceforth we will omit the underlines and write all values in the list form. Figure 2.2 gives some examples of elements in ID and their list representations.

Valuedin ID Representation |d| l(d)

nil nil 1 0

(a.(b.nil)) (a b) 3 2

(a.((b.(c.nil)).(d.nil))) (a (b c) d) 6 3 ((a.(((b.nil).nil).nil)).nil) ((a ((b)))) 6 1

Figure 2.2: Some trees and their list representation

The first example in the preceding subsection can now be expressed as saying that the program reverses lists: if Xwas initially bound to input (d0· · ·dn) then Y is bound to

(dn· · ·d0) when execution reaches the final write command.

2.1.6

Numbers

WHILE has only one atom, so how can we compute with numbers? One idea is to represent the numbernby a list of lengthn.

Definition 2.1.8 Definen=niln, where

nil0 = nil = ()

niln+1 = (nil.niln) = (nil . . . nil

| {z }

n+1times )

and letN={n|n∈IN}. The elements ofN are called numerals. 2 As a matter of convenience, we will omit underlines and simply write0,1,2,. . . instead of 0,1,2, . . .ornil0,nil1, nil2,· · ·. With the representation in this definition, while E do Cmeans: as long asEdoes not evaluate to 0, executeC. As two very simple examples, thesuccessor andpredecessor functions are computed by:

read X; (* succ *) read X; (* pred *)

Y := cons nil X; Y:=tl X;

write Y write Y

Here is a program for adding two numbers (note thatXYis a single variable, whose value is a pair):

read XY; (* add X Y *) X := hd XY; Y := tl XY; while X do Y := cons nil Y; X := tl X; write Y

More programs computing with numbers are examined in the Exercises.