YAP 7.1.0
queues.yap
Go to the documentation of this file.
1/**
2 * @file queues.yap
3 * @author R.A.O'Keefe
4 * @date Friday November 18th, 1983, 8:09:31
5 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
6 * @date 1999-
7 *
8 * @brief define queue operations
9 *
10 *
11*/
12
13:- module(queues, [
14 make_queue/1, % create empty queue
15 join_queue/3, % add element to end of queue
16 list_join_queue/3, % add many elements to end of queue
17 jump_queue/3, % add element to front of queue
18 list_jump_queue/3, % add many elements to front of queue
19 head_queue/2, % look at first element of queue
20 serve_queue/3, % remove first element of queue
21 length_queue/2, % count elements of queue
22 empty_queue/1, % test whether queue is empty
23 list_to_queue/2, % convert list to queue
24 queue_to_list/2 % convert queue to list
25 ]).
26
27
28/** @defgroup queues Queues
29@ingroup YAPLibrary
30@{
31
32The following queue manipulation routines are available once
33included with the `use_module(library(queues))` command. Queues are
34implemented with difference lists.
35
36In this package, a queue is represented as a term Front-Back, where
37 Front is a list and Back is a tail of that list, and is normally a
38 variable. join_queue will only work when the Back is a variable,
39 the other routines will accept any tail. The elements of the queue
40 are the list difference, that is, all the elements starting at Front
41 and stopping at Back. Examples:
42
43 [a,b,c,d,e|Z]-Z has elements a,b,c,d,e
44 [a,b,c,d,e]-[d,e] has elements a,b,c
45 Z-Z has no elements
46 [1,2,3]-[1,2,3] has no elements
47
48
49*/
50
51/**
52
53 @pred make_queue(+ _Queue_)
54
55
56Creates a new empty queue. It should only be used to create a new queue.
57
58
59*/
60
61
62/** @pred empty_queue(+ _Queue_)
63
64
65Tests whether the queue is empty.
66
67
68*/
69/** @pred head_queue(+ _Queue_, ? _Head_)
70
71
72Unifies Head with the first element of the queue.
73
74
75*/
76/** @pred join_queue(+ _Element_, + _OldQueue_, - _NewQueue_)
77
78
79Adds the new element at the end of the queue.
80
81
82*/
83/** @pred jump_queue(+ _Element_, + _OldQueue_, - _NewQueue_)
84
85
86Adds the new element at the front of the list.
87
88
89*/
90/** @pred length_queue(+ _Queue_, - _Length_)
91
92
93Counts the number of elements currently in the queue.
94
95
96*/
97/** @pred list_join_queue(+ _List_, + _OldQueue_, - _NewQueue_)
98
99
100Ads the new elements at the end of the queue.
101
102
103*/
104/** @pred list_jump_queue(+ _List_, + _OldQueue_, + _NewQueue_)
105
106
107Adds all the elements of _List_ at the front of the queue.
108
109
110*/
111/** @pred list_to_queue(+ _List_, - _Queue_)
112
113
114Creates a new queue with the same elements as _List._
115
116
117*/
118/** @pred queue_to_list(+ _Queue_, - _List_)
119
120
121Creates a new list with the same elements as _Queue_.
122
123
124
125
126 */
127/** @pred serve_queue(+ _OldQueue_, + _Head_, - _NewQueue_)
128
129
130Removes the first element of the queue for service.
131
132
133*/
134:- append/3use_module(library(lists), []).
135
136/*
137:- mode
138 make_queue(-),
139 join_queue(+, +, -),
140 list_join_queue(+, +, -),
141 jump_queue(+, +, -),
142 list_jump_queue(+, +, -),
143 head_queue(+, ?),
144 serve_queue(+, ?, -),
145 length_queue(+, ?),
146 length_queue(+, +, +, -),
147 empty_queue(+),
148 list_to_queue(+, -),
149 queue_to_list(+, -),
150 queue_to_list(+, +, -).
151*/
152
153% make_queue(Queue)
154% creates a new empty queue. It will also match empty queues, but
155% because Prolog doesn't do the occurs check, it will also match
156% other queues, creating circular lists. So this should ONLY be
157% used to make new queues.
158
159make_queue(X-X).
160
161
162
163% join_queue(Element, OldQueue, NewQueue)
164% adds the new element at the end of the queue. The old queue is
165% side-effected, so you *can't* do
166% join_queue(1, OldQ, NewQ1),
167% join_queue(2, OldQ, NewQ2).
168% There isn't any easy way of doing that, sensible though it might
169% be. You *can* do
170% join_queue(1, OldQ, MidQ),
171% join_queue(2, MidQ, NewQ).
172% See list_join_queue.
173
174join_queue(Element, Front-[Element|Back], Front-Back).
175
176
177
178% list_join_queue(List, OldQueue, NewQueue)
179% adds the new elements at the end of the queue. The elements are
180% added in the same order that they appear in the list, e.g.
181% list_join_queue([y,z], [a,b,c|M]-M, [a,b,c,y,z|N]-N).
182
183list_join_queue(List, Front-OldBack, Front-NewBack) :-
184 append(List, OldBack, NewBack).
185
186
187
188% jump_queue(Element, OldQueue, NewQueue)
189% adds the new element at the front of the list. Unlike join_queue,
190% jump_queue(1, OldQ, NewQ1),
191% jump_queue(2, OldQ, NewQ2)
192% *does* work, though if you add things at the end of NewQ1 they
193% will also show up in NewQ2. Note that
194% jump_queue(1, OldQ, MidQ),
195% jump_queue(2, MidQ, NewQ)
196% makes NewQ start 2, 1, ...
197
198jump_queue(Element, Front-Back, [Element|Front]-Back).
199
200
201
202% list_jump_queue(List, OldQueue, NewQueue)
203% adds all the elements of List at the front of the queue. There are
204% two ways we might do this. We could add all the elements one at a
205% time, so that they would appear at the beginning of the queue in the
206% opposite order to the order they had in the list, or we could add
207% them in one lump, so that they have the same order in the queue as
208% in the list. As you can easily add the elements one at a time if
209% that is what you want, I have chosen the latter.
210
211list_jump_queue(List, OldFront-Back, NewFront-Back) :-
212 append(List, OldFront, NewFront).
213% reverse(List, OldFront, NewFront). % for the other definition
214
215
216
217% head_queue(Queue, Head)
218% unifies Head with the first element of the queue. The tricky part
219% is that we might be at the end of a queue: Back-Back, with Back a
220% variable, and in that case this predicate should not succeed, as we
221% don't know what that element is or whether it exists yet.
222
223head_queue(Front-Back, Head) :-
224 Front \== Back, % the queue is not empty
225 Front = [Head|_].
226
227
228
229% serve_queue(OldQueue, Head, NewQueue)
230% removes the first element of the queue for service.
231
232serve_queue(OldFront-Back, Head, NewFront-Back) :-
233 OldFront \== Back,
234 OldFront = [Head|NewFront].
235
236
237
238% empty_queue(Queue)
239% tests whether the queue is empty. If the back of a queue were
240% guaranteed to be a variable, we could have
241% empty_queue(Front-Back) :- var(Front).
242% but I don't see why you shouldn't be able to treat difference
243% lists as queues if you want to.
244
245empty_queue(Front-Back) :-
246 Front == Back.
247
248
249
250% length_queue(Queue, Length)
251% counts the number of elements currently in the queue. Note that
252% we have to be careful in checking for the end of the list, we
253% can't test for [] the way length(List) does.
254
255length_queue(Front-Back, Length) :-
256 length_queue(Front, Back, 0, N),
257 Length = N.
258
259length_queue(Front, Back, N, N) :-
260 Front == Back, length_queue.
261length_queue([_|Front], Back, K, N) :-
262 L is K+1,
263 length_queue(Front, Back, L, N).
264
265
266
267% list_to_queue(List, Queue)
268% creates a new queue with the same elements as List.
269
270list_to_queue(List, Front-Back) :-
271 append(List, Back, Front).
272
273
274
275% queue_to_list(Queue, List)
276% creates a new list with the same elements as Queue.
277
278queue_to_list(Front-Back, List) :-
279 queue_to_list(Front, Back, List).
280
281queue_to_list(Front, Back, Ans) :-
282 Front == Back, queue_to_list, Ans = [].
283queue_to_list([Head|Front], Back, [Head|Tail]) :-
284 queue_to_list(Front, Back, Tail).
285
286/** @} */
287
288
use_module( +Files )
append(? List1,? List2,? List3)
empty_queue(+ Queue)
head_queue(+ Queue, ? Head)
join_queue(+ Element, + OldQueue, - NewQueue)
jump_queue(+ Element, + OldQueue, - NewQueue)
length_queue(+ Queue, - Length)
list_join_queue(+ List, + OldQueue, - NewQueue)
list_jump_queue(+ List, + OldQueue, + NewQueue)
list_to_queue(+ List, - Queue)
make_queue(+ Queue)
queue_to_list(+ Queue, - List)
serve_queue(+ OldQueue, + Head, - NewQueue)