Subsections

- Exercises

# Queues

Consider the problem of representing a queue. We shall suppose that the queue is at a football match and that each fan in the queue has a name, in the ordinary sense, and a ticket number. Rather than just present the solution to this problem, we shall discuss the problem in detail and show why the solution is what it is.

A suitable mode for the fan would be `FAN`:

       MODE FAN = STRUCT(STRING name,INT ticket)

but what would be a suitable declaration for a queue? At first sight, it would appear that a flexible name which can refer to a multiple of fans would be suitable:

       MODE QUEUE = FLEX[1:0]FAN

but there are difficulties. Firstly, the only way a new fan could be added to the queue would be to assign a whole new multiple to a name (in the Algol 68 sense) referring to the queue:

       QUEUE q; q:=q+FAN("Jim",1)

assuming that the operator `+` has been declared with the header

       OP + = ([]QUEUE a,FAN b)[]QUEUE:

If the queue were long, this would be very inefficient. Secondly, given a particular fan, how would we find the fan behind him or her? Knowing the subscript of the fan would seem to be the answer, but what happens if someone joins the queue somewhere in front of the fan in question? Given that there might be several fans under consideration, the program would have to update all the relevant subscripts and keep a record of which subscripts would be relevant.

The solution is to represent a queue as a recursive structure:

       MODE QUEUE=STRUCT(FAN fan,REF QUEUE next)

Then a queue with two fans in it could be represented by the diagram

where the mode of each box is `QUEUE` and `F` and `RQ` stand for `FAN` and `REF QUEUE` respectively. Notice that the `next` field of the first structure refers to the structure on its right. The `next` field of the second structure does not refer to anything.

From the declaration of the mode `QUEUE`, we can see that the `next` field of the structure is a name with mode `REF QUEUE`. It would appear that it is possible to construct a queue in the way depicted by the last diagram: each `next` field of each structure would refer to the next structure (of mode `QUEUE`) and the last `next` field would have the mode `REF QUEUE` and value `NIL`.

Now consider adding another `QUEUE` to the right-hand end of the queue. We immediately run into a difficulty. The value of the `next` field of the last `QUEUE` is `NIL` with mode `REF QUEUE`. However, we cannot assign to `NIL`, nor can we replace the name `NIL` with another name to make it refer to a new `QUEUE`. The reason is that a name of mode `REF QUEUE` can only be replaced by another name of mode `REF QUEUE` if the first name is referred to by a name of mode `REF REF QUEUE`. In other words, instead of making the structures have mode `QUEUE`, we should make them have mode `REF QUEUE`. In section 7.2, on field selection, we pointed out that the modes of the fields of a structure name are all preceded by a `REF`. This also applies to a recursively-defined structure. In this case, the mode of the `next` field becomes `REF REF QUEUE` and could refer to `NIL` (with mode `REF QUEUE`) or to another structure of mode `REF QUEUE`. We can depict this as

where `RQ`, `RRQ` and `RF` represent the modes `REF QUEUE`, `REF` `REF` `QUEUE` and `REF FAN` respectively.

Now let us consider how such a queue could be created. Since the length of the queue at the time the program is written is unknown (and will change as fans join or leave the queue), it is not possible to have an identifier for each structure forming the queue. Instead, we can create anonymous names using a generator. However, we must be able to refer to the queue in order to manipulate it. Let us declare a name, identified by `head`, to refer to the beginning of the queue:

       REF QUEUE head:=NIL

We have made it refer to `NIL` (with mode `REF QUEUE`) because the queue is currently empty. Using the suggestion of the last section, we shall declare

       REF QUEUE nilq = NIL;
       REF QUEUE head:=nilq

where `head` has the mode `REF REF QUEUE`.

Let us assign the first fan to the queue:

       head:=LOC QUEUE:=(("Jim",1),nilq)

We can represent this by the diagram

We can now assign another fan to the queue:

       next OF head:=LOC QUEUE:=(("Fred",2),nilq)

Let us be quite clear what is happening here. The mode of `head` is `REF REF QUEUE`. It is a name which refers to a name so it has no fields. We can select fields only from a `QUEUE` or a `REF QUEUE`. However, the context of a selection is weak(see section 10.3) and so only weak-dereferencing is allowed. Thus in

       next OF head

`head` is dereferenced to mode `REF QUEUE` and the `next` field selected (with mode `REF REF QUEUE`). The anonymous name `LOC QUEUE` has mode `REF QUEUE`, so the structure display (with mode `QUEUE`) is assigned to it, and it in turn is assigned to `next OF head` without dereferencing. This means that the `nilq` which `next OF head` referred to after the first fan `("Jim",1)` was added to the queue has been replaced by the second `LOC` `QUEUE` which is what we wanted. We can now depict the queue by

We could now extend the queue by writing

       next OF next OF queue:=LOC QUEUE

but since we do not know how long the queue might become, clearly we cannot go on writing

       next OF next OF ...

What we need is some way of referring to the tail of the queue without lots of selections. Because the tail of the queue always has mode `REF REF QUEUE` (it is the `next` field of a `REF QUEUE`), what we need is a name of mode `REF REF REF QUEUE` (yes, three `REF`s). Here it is:

       REF REF QUEUE tail;

but again we run into a difficulty (the last one). When the queue is empty, `head` refers to `nilq`, but what does `tail` refer to since we cannot select from `nilq` (because it is `NIL`)? The solution is to make `head` have the mode `REF REF REF QUEUE` as well as `tail` and generate a name of mode `REF REF QUEUE` to refer to `nilq`! (bear with it, we're almost there):

       tail:=head:=LOC REF QUEUE:=nilq

In this triple assignment, only `head` is dereferenced. We can depict this as

Now we can assign the first fan to the head of the queue:

       REF REF QUEUE(head):=LOC QUEUE:=
             (("Jim",1),nilq))

and make `tail` refer to the tail of the queue with

       tail:=next OF head

in which `head` is dereferenced twice, but the selection is not dereferenced at all. The queue can now be depicted as shown below.

A queue is one example of what is called a linked-list.

## Exercises

11.16
  Extend the queue by assigning another `REF QUEUE` to `tail`. Ans
11.17
  Now make `tail` refer to the tail of the queue again. Ans
11.18
  Has the name referred to by `head` changed after adding the new `REF QUEUE`? Ans