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 REFs). 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.
REF QUEUE to
tail. Ans
tail refer to the tail of the queue again.
Ans
head changed after adding the
new REF QUEUE? Ans
Sian Mountbatten 2012-01-19