TEACH POPCOURSE3 - Words, lists and hats

Contents


Words

So far, our POP-11 programs have only used one type of `data-object', namely numbers. However, we often need more complex forms of data. In particular we often need to be able to use symbols, i.e., sequences of characters that can be used as labels. In POP-11, symbols are known as `words'. To create a word object we wrap double quotes around an unbroken sequence of alphabetic characters; e.g.

"hello"
Technically, this is a POP-11 command (expression) that produces as a value a data-object called a word. We can assign words to variables in the same way we assign numbers. Thus

vars xxx;
"hello" -> xxx;
xxx ==>
causes

** hello
to be printed out.

Experiment: Write the POP-11 code to print out the word `goodbye'.

Like variable names, word objects can be made up using alphabetic characters, numeric characters and the underscore. They are not allowed to begin with a number or the underscore and they are not allowed to contain any hyphens.


Lists

Another important data object in POP-11 is the `list'. A list is just a sequence of arbitrary values. Lists are constructed using special brackets, rather like words---except the brackets for lists are the square brackets `[' and `]'. To construct a list we type in an opening square bracket, followed by the sequence of values we want to be in the list, and finish off with a closing square bracket. Each value should be separated from the next by a space. To construct a list that contains the value `1' followed by the value `2' followed by the value `3' we do the following.

[1 2 3]
Printed out this object looks exactly like what the text we typed in.

[1 2 3] ==>
** [1 2 3]
Note the slight difference between POP-11's behaviour with respect to words and lists. When we print out words we do not see the double-quote marks. However, when we print out lists we do see the square-brackets.

If we want to produce, say, the third value in a list, we can do so by putting the number 3 in round brackets after the list itself. Thus

vars numbers;
[100 200 300] -> numbers;
numbers(2) ==>
prints

** 200
This is referred to as `subscripting' the list.

If we want to replace a particular item in a list with another item we can assign the value to that position in the list using the same convention. For example

"four" -> numbers(3);
The new value of `numbers' is thus

numbers ==>
** [100 200 four]
Note that assigning a new value to a particular subscript of a list leaves the rest of the list intact. It does not push the existing elements along. It simply overwrites the subscripted element.

Experiment: load the initial assignment to `numbers' above. Then assign the list [the cat sat] to the variable `sentence'. Finally assign the second element of the list in `sentence' to the third position of the list in `numbers'. After doing this, the value of `sentence' should still be [the cat sat] but the value of `numbers' should now be [100 200 cat]. Note how assigning a value out of a list does not remove it from that list. Note also that assigning a value into a particular position of a list does not affect the values in other positions in any way.

There is no restriction over the values that we can put in a list. This means we can put lists inside lists if we want.

vars allnumbers;
[[100 200 300] [1000 2000 3000]] -> allnumbers;
If we want to get at the third element of the second list in `allnumbers', we have to subscript the variable twice---once to dig out the second list and again to dig out its third element. Thus

vars list;
allnumbers(2) -> list;
list(3) ==>
prints out

** 3000
We can do the two subscripts in one go if we want:

allnumbers(2)(3) ==>
** 3000
Experiment: execute the initial assignment to `allnumbers' above and then, using two subscripts, assign the value 4000 to the second position of the first element of `allnumbers'. The new value of `allnumbers' should be [[100 4000 300][1000 2000 3000]].

It is important to note that when POP-11 is constructing a list (i.e., is in between `[' and `]'), it assumes that everything it comes across is either a word or a number. This means that if we do

[2 + 2] ==>
POP-11 prints out

** [2 + 2]
In this situation it thinks that `+' is a word. POP-11 makes this assumption because lists usually do contain words. Assuming that everything inside list brackets is either a number or a word saves the user the trouble of typing in lots of word-quotes. It means that the list [bug1 bug2 bug3] can be constructed by typing

[bug1 bug2 bug3]
rather than

["bug1" "bug2" "bug3"]
Experiment: print out this last list and explain why POP-11 prints it out the way it does.

Experiment: construct a list that contains all the whole numbers between 5 and 9. Then declare a variable called `num' and assign the third element of the list to it. Finally, print out the value of `num'. POP-11 should print `** 7'.


Hats and double-hats

If we want POP-11 to include the value of an expression like `2 + 2' in a list we have to use the `hat' symbol `^'. If POP-11 comes across the hat symbol when it is constructing a list, instead of just including the hat at that point, it includes the value of the variable or bracketed expression that appears immediately after the hat. This means that once we have done the following

vars english roman;
[one two three] -> english;
[i ii iii] -> roman;
we can do this.

[^english ^roman] ==>
** [[one two three] [i ii iii]]
When we use the hat symbol this way POP-11 includes the value of the relevant variable without changing it in any way. However, in some situations, the value we want to insert is a list itself. And what we would like is to merge the list in, rather than insert it as a single element.

POP-11 caters to this need with the so-called `double-hat' symbol, which is just two hats in a row, i.e., `^^'. If POP-11 encounters this symbol when constructing a list it merges in the elements of the list, which is just the value of the following variable. If the value of the following variable is not a list, POP-11 complains appropriately.

[^^english ^^roman] ==>
prints out

** [one two three i ii iii]
but

vars num;
2 -> num;
[^^english ^^num] ==>
causes a mishap in which POP-11 issues the complaint `LIST NEEDED' because the value of `num' is not a list.

We can use the hat symbol to obtain the value of an arbitrarily long piece of POP-11 code, provided that that code produces at least one value. To make this happen we put the code in round brackets to show where it begins and ends, and precede it with the hat. Thus

[^(2 + 2)] ==>
prints out

** [4]
and

[^(vars x; 3 -> x; x + x)] ==>
produces

** [6]
If the value produced by the code in the round brackets is a list, and if we want to merge the elements of that list in, we should use `^^' rather than `^'.

Experiment: test to see what POP-11 does if you miss out the round brackets in the example above.

Experiment: if you have a variable called `num' whose value is 2, what list is constructed by [^num + ^num]?


Adding an item to the front of a list

Elements of a list can be straightforwardly overwritten using subscripting assignments. For example, if we set up a list as follows

vars description;
[dooby bad bug] -> description;
The value of description is just the list we assigned to it. Thus

description ==>
** [dooby bad bug]
To overwrite the first element of the list we just execute the relevant assignment to position 1 of the `description' list.

"very" -> description(1);
description ==>
** [very bad bug]
Using hats and double-hats we can also add items to an existing list. To add element(s) to the front or back of the list we reconstruct the list, using hats and double-hats to include the new elements in the right places. If we want to add the word `a' to the front of the list `description' we have to do this.

[a ^^description] -> description;
Here we have constructed a new list which merges in the old value of `description' and assigned it to be the new value of `description'. This achieves the effect of adding `a' to the front of the list. Thus

description ==>
** [a very bad bug]
Experiment: write down an assignment that will have the effect of adding the words `Here is' to the front of the list in `description'.

If we want to add the value of a variable to the front of a list then we need to use both the double-hat and the single-hat. For example, if we have a list called `silly' and a variable called `new' set up as follows

vars silly, new;
[foo bang ding] -> silly;
"zog" -> new;
we can effectively add the value of `new' onto the front of `silly' by reconstructing the list using a hat in front of `new' and a double-hat in front of `silly', and assigning the list back to `silly'.

[^new ^^silly] -> silly;
The list called `silly' now has the value of `new' tacked on the front.

silly ==>
** [zog foo bang ding]
Experiment: load the initializations of `silly' and `new' above and then write down an assignment that will add the value of `new' to the back of the list in `silly'. Next write down an assignment that will assign the word `goo' to the second position of the list `silly'. The value of `silly' should now be [foo goo ding zog].


Using lists to construct objects in the bugworld

In LIB POPBUGS we use lists in conjunction with the special variable `pb_spec' to place objects into the simulated world. To create a new object we first construct a list of sublists. Each sublist should specify an attribute (e.g. `colour') and a value for that attribute (e.g., `red'). Next, we assign the list to `pb_spec'. LIB POPBUGS reacts to the updating of this variable by constructing the relevant object and including it in the display. Before experimenting with this make sure you have LIB POPBUGS loaded; i.e., do

lib popbugs
Now try the following.

1 -> pb_new_world;
[[name b1]
 [shape circle]
 [position [25 30]]
 [dimensions [20 20]]] -> pb_spec;
The first command initializes the world to contain a single bug. The second effectively creates a circular, static object at the specified coordinates. Note that positions are given by specifying a list containing east-west coordinate (the `X' coordinate) and a north-south coordinate (the `Y' coordinate), with both coordinates being whole numbers between 1 and 100. We can modify and/or add to the attributes of this object by assigning another list to `pb_spec'. Provided that we specify the name we used before, the program knows we want to add to (or change) the attributes for an existing object.

[[name b1][colour pink][dimensions [30 15]]] -> pb_spec;
If we use a different name, a new object is created.

[[name b2][colour green][position [80 80]]] -> pb_spec;
Note how assignments to `pb_spec' can be used to change the position of an existing object.


Constructing a wall with a repeat loop

We can use repeat loops in conjunction with assignments to `pb_spec' to build complex structures in the bugworld. For example, we could build a `wall' of different coloured rectangular obstacles using the following code.

vars num, colours, col, x, y;
20 -> y;
0 -> x;
1 -> pb_new_world;
0 -> num;
[red green blue yellow cyan black pink brown orange] -> colours;

repeat 9 times
   num + 1 -> num;
   colours(num) -> col;
   x + 5 -> x;
   [[shape box][colour ^col][position [^x ^y]][dimensions [5 5]]]
      -> pb_spec;
endrepeat;
In this program we use a `num' variable to hold a number which we increment each time we go around the repeat loop. We also use a `colours' variable which we initialize to be a list of nine colour names. In the repeat loop itself we increment the num variable and then use it to subscript a new colour from the `colours' list. We then create a new, rectangular block with an X coordinate whose value is 5 plus the X coordinate of the previous block, and a Y coordinate of 20. The effect produced is a horizontal wall of nine, differently coloured rectangles.

Experiment: modify the code so that it generates a wall of just three blocks, all in the same colour.

To make this code more useful we could wrap it up into a named procedure like this.

define wall;
   0 -> num;
   [red green blue yellow cyan black pink brown orange] -> colours;
   repeat 9 times
      num + 1 -> num;
      colours(num) -> col;
      x + 5 -> x;
      [[shape box][colour ^col][position [^x ^y]]
       [dimensions [5 5]]] -> pb_spec;
   endrepeat;
enddefine;
We can now use the `wall' procedure to produce walls in different positions by calling the procedure after changing the initial values of `x' and `y'.

30 -> x;
60 -> y;
wall();
40 -> x;
90 -> y;
wall();
Experiment: find out what happens if you the bug crashes into a wall.


Tip of the day: remembering to clear your output file

In the Poplog system, output is always printed into your output file (normally called `output.p'). If you do a lot of work you can end up with a huge output file. And eventually, this can cause you to run out of memory. The solution is to remember to always clear your output file at the end of every session. You can do this by giving the Ved `clear' command inside the output file.


Exercises

To test your understanding of the material in this file you should do the following exercises. First, copy them into a file of your own. Then, edit in answers underneath each question and print out the file.

Where you have written some code that produces some output, you should include that output (even if it is a mishap message) as part of your answer. The easiest way to do this is to copy your code into the output file (`output.p') and execute it from there. The output will then be printed out right underneath the code.

If you find you are having difficulty with a particular problem, work back through the file looking for relevant information. Use the index mechanism (i.e., the `g' command) and the search command `/' to locate the information you need.

  1. Write down the POP-11 code to construct a list containing the sequence of words `red', `yellow', `blue', and assign it to the variable `words'.

  2. A list object is a sequential data structure that has a specific `length', i.e., number of components. Taking into account the rules for word- and list-construction given above, work out (by hand) the lengths of the following lists.

    [a b c]; [abc]; [ [a b c] ]; [ ]; [list6]; [6list]; [^^list ^^list] (given that the value of `list' is `[a b c]') [a];

(3) Construct the list [a b c d e a b c i j k] using only hats, double hats, and the variables u, v, w, x, y and z (assigned as below).

vars u, v, w, x, y, z; a -> w; [b c d] -> u; [d e] -> y; [a b c] -> x; [i j k] -> z;

  1. Construct the list [one two three] using only hats, double hats and the variables x and y (assigned as below).

    vars x, y;
    "one" -> x;
    [two three] -> y;
    
  2. Construct the list [one two three] using only single hats, subscripting expressions and the variables x, y and z (assigned as below).

    vars x, y, z;
    [one] -> x;
    [two] -> y;
    [three] -> z;
    
  3. What happens if you construct a list in which a hat is followed by a valid POP-11 statement, i.e., a piece of valid code that does not produce a value? Give an example to illustrate your answer. (Note, to get this right you need to have clearly understood the difference between commands that produce values (expressions) and command which don't (statements).

  4. Write a new versions of the `wall' procedure called `vwall' which produces vertical walls.

  5. Write a procedure that when called uses the `wall' and `vwall' procedures to build a maze in the bugworld.

  6. Write a procedure that moves the bug to the centre of the maze (starting from the boundary) without crashing into any of the walls. (Note that the bug can be moved to the edge of the arena using the repositioning method described above provided the assignment to pb_spec includes [name bug1].)

Revision exercises

Do not do the following exercises on your first reading of this file. Save them from revision purposes.


Quick reference

The following list contains the commands that have been introduced in this file. If you are keeping a file of commands for easy reference, you might want to add these items to that file.

""     a pair of double quotes construct a word object
(n)    a bracketed whole number subscripts the preceding data-object
[]     a pair of square brackets construct a list of items
^      the hat inserts value of the following variable (or code)
^^     double-hat merges in the elements of following list-variable

Moving on

If you have completed all the exercises above then you are ready to move on to TEACH POPCOURSE4. You can do this by giving the command `teach popcourse4'.


Page created on: Fri Apr 26 09:34:50 BST 2002
Feedback to Chris Thornton
hits this year