* Grammar fix.
[bpt/guile.git] / libguile / list.c
CommitLineData
f2c9fcb0 1/* Copyright (C) 1995,1996,1997, 2000 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd 45\f
a0599745
MD
46#include "libguile/_scm.h"
47#include "libguile/eq.h"
20e6290e 48
a0599745
MD
49#include "libguile/validate.h"
50#include "libguile/list.h"
0f2d19dd
JB
51
52#ifdef __STDC__
53#include <stdarg.h>
54#define var_start(x, y) va_start(x, y)
55#else
56#include <varargs.h>
57#define var_start(x, y) va_start(x)
58#endif
59
60\f
df13742c 61/* creating lists */
0f2d19dd 62
0f2d19dd
JB
63SCM
64scm_listify (SCM elt, ...)
0f2d19dd
JB
65{
66 va_list foo;
2de14ecd
GB
67 SCM answer = SCM_EOL;
68 SCM *pos = &answer;
0f2d19dd
JB
69
70 var_start (foo, elt);
fbd485ba 71 while (! SCM_UNBNDP (elt))
0f2d19dd
JB
72 {
73 *pos = scm_cons (elt, SCM_EOL);
25d8012c 74 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
75 elt = va_arg (foo, SCM);
76 }
77 return answer;
78}
79
80
3b3b36dd 81SCM_DEFINE (scm_list, "list", 0, 0, 1,
1bbd0b84 82 (SCM objs),
5352393c
MG
83 "Return a list containing @var{objs}, the arguments to\n"
84 "@code{list}.")
1bbd0b84 85#define FUNC_NAME s_scm_list
0f2d19dd
JB
86{
87 return objs;
88}
1bbd0b84 89#undef FUNC_NAME
0f2d19dd
JB
90
91
26a379b2
MD
92#if (SCM_DEBUG_DEPRECATED == 0)
93
94SCM_REGISTER_PROC (s_list_star, "list*", 1, 0, 1, scm_cons_star);
95
96#endif /* SCM_DEBUG_DEPRECATED == 0 */
97
98SCM_DEFINE (scm_cons_star, "cons*", 1, 0, 1,
1bbd0b84 99 (SCM arg, SCM rest),
5352393c
MG
100 "Like @code{list}, but the last arg provides the tail of the\n"
101 "constructed list, returning @code{(cons @var{arg1} (cons\n"
a17bb5fd 102 "@var{arg2} (cons @dots{} @var{argn})))}. Requires at least one\n"
5352393c
MG
103 "argument. If given one argument, that argument is returned as\n"
104 "result. This function is called @code{list*} in some other\n"
105 "Schemes and in Common LISP.")
26a379b2 106#define FUNC_NAME s_scm_cons_star
a610b8d9 107{
af45e3b0
DH
108 SCM_VALIDATE_REST_ARGUMENT (rest);
109 if (!SCM_NULLP (rest))
a610b8d9
MD
110 {
111 SCM prev = arg = scm_cons (arg, rest);
e1385ffc 112 while (SCM_NNULLP (SCM_CDR (rest)))
a610b8d9
MD
113 {
114 prev = rest;
115 rest = SCM_CDR (rest);
116 }
117 SCM_SETCDR (prev, SCM_CAR (rest));
118 }
119 return arg;
120}
1bbd0b84 121#undef FUNC_NAME
a610b8d9 122
0f2d19dd
JB
123
124\f
df13742c 125/* general questions about lists --- null?, list?, length, etc. */
0f2d19dd 126
3b3b36dd 127SCM_DEFINE (scm_null_p, "null?", 1, 0, 0,
1bbd0b84 128 (SCM x),
5352393c 129 "Return @code{#t} iff @var{x} is the empty list, else @code{#f}.")
1bbd0b84 130#define FUNC_NAME s_scm_null_p
0f2d19dd 131{
2de14ecd 132 return SCM_BOOL (SCM_NULLP (x));
0f2d19dd 133}
1bbd0b84 134#undef FUNC_NAME
0f2d19dd 135
2de14ecd 136
3b3b36dd 137SCM_DEFINE (scm_list_p, "list?", 1, 0, 0,
1bbd0b84 138 (SCM x),
5352393c 139 "Return @code{#t} iff @var{x} is a proper list, else @code{#f}.")
1bbd0b84 140#define FUNC_NAME s_scm_list_p
0f2d19dd 141{
2de14ecd 142 return SCM_BOOL (scm_ilength (x) >= 0);
0f2d19dd 143}
1bbd0b84 144#undef FUNC_NAME
0f2d19dd
JB
145
146
df13742c 147/* Return the length of SX, or -1 if it's not a proper list.
448a3bc2 148 This uses the "tortoise and hare" algorithm to detect "infinitely
df13742c
JB
149 long" lists (i.e. lists with cycles in their cdrs), and returns -1
150 if it does find one. */
c014a02e
ML
151long
152scm_ilength(SCM sx)
0f2d19dd 153{
c014a02e 154 long i = 0;
e1385ffc
GB
155 SCM tortoise = sx;
156 SCM hare = sx;
df13742c 157
0f2d19dd 158 do {
e1385ffc 159 if (SCM_NULLP(hare)) return i;
ff467021 160 if (SCM_NCONSP(hare)) return -1;
df13742c 161 hare = SCM_CDR(hare);
0f2d19dd 162 i++;
e1385ffc 163 if (SCM_NULLP(hare)) return i;
ff467021 164 if (SCM_NCONSP(hare)) return -1;
df13742c 165 hare = SCM_CDR(hare);
0f2d19dd 166 i++;
448a3bc2
JB
167 /* For every two steps the hare takes, the tortoise takes one. */
168 tortoise = SCM_CDR(tortoise);
0f2d19dd 169 }
fbd485ba 170 while (! SCM_EQ_P (hare, tortoise));
df13742c 171
448a3bc2 172 /* If the tortoise ever catches the hare, then the list must contain
df13742c 173 a cycle. */
0f2d19dd
JB
174 return -1;
175}
176
2de14ecd 177
3b3b36dd 178SCM_DEFINE (scm_length, "length", 1, 0, 0,
1bbd0b84 179 (SCM lst),
5352393c 180 "Return the number of elements in list @var{lst}.")
1bbd0b84 181#define FUNC_NAME s_scm_length
0f2d19dd 182{
c014a02e 183 long i;
3b3b36dd 184 SCM_VALIDATE_LIST_COPYLEN (1,lst,i);
0f2d19dd
JB
185 return SCM_MAKINUM (i);
186}
1bbd0b84 187#undef FUNC_NAME
0f2d19dd
JB
188
189
190\f
df13742c 191/* appending lists */
0f2d19dd 192
a1ec6916 193SCM_DEFINE (scm_append, "append", 0, 0, 1,
1bbd0b84 194 (SCM args),
5352393c
MG
195 "Return a list consisting of the elements the lists passed as\n"
196 "arguments.\n"
1e6808ea 197 "@lisp\n"
5352393c
MG
198 "(append '(x) '(y)) @result{} (x y)\n"
199 "(append '(a) '(b c d)) @result{} (a b c d)\n"
200 "(append '(a (b)) '((c))) @result{} (a (b) (c))\n"
1e6808ea 201 "@end lisp\n"
5352393c
MG
202 "The resulting list is always newly allocated, except that it\n"
203 "shares structure with the last list argument. The last\n"
204 "argument may actually be any object; an improper list results\n"
205 "if the last argument is not a proper list.\n"
1e6808ea 206 "@lisp\n"
5352393c
MG
207 "(append '(a b) '(c . d)) @result{} (a b c . d)\n"
208 "(append '() 'a) @result{} a\n"
1e6808ea 209 "@end lisp")
1bbd0b84 210#define FUNC_NAME s_scm_append
0f2d19dd 211{
af45e3b0
DH
212 SCM_VALIDATE_REST_ARGUMENT (args);
213 if (SCM_NULLP (args)) {
214 return SCM_EOL;
215 } else {
216 SCM res = SCM_EOL;
217 SCM *lloc = &res;
218 SCM arg = SCM_CAR (args);
219 args = SCM_CDR (args);
220 while (!SCM_NULLP (args)) {
221 while (SCM_CONSP (arg)) {
222 *lloc = scm_cons (SCM_CAR (arg), SCM_EOL);
223 lloc = SCM_CDRLOC (*lloc);
224 arg = SCM_CDR (arg);
225 }
226 SCM_VALIDATE_NULL (SCM_ARGn, arg);
227 arg = SCM_CAR (args);
228 args = SCM_CDR (args);
229 };
230 *lloc = arg;
0f2d19dd
JB
231 return res;
232 }
0f2d19dd 233}
1bbd0b84 234#undef FUNC_NAME
0f2d19dd
JB
235
236
a1ec6916 237SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
1e6808ea
MG
238 (SCM lists),
239 "A destructive version of @code{append} (@pxref{Pairs and\n"
7a095584 240 "Lists,,,r5rs, The Revised^5 Report on Scheme}). The cdr field\n"
1e6808ea
MG
241 "of each list's final pair is changed to point to the head of\n"
242 "the next list, so no consing is performed. Return a pointer to\n"
243 "the mutated list.")
1bbd0b84 244#define FUNC_NAME s_scm_append_x
0f2d19dd 245{
1e6808ea 246 SCM_VALIDATE_REST_ARGUMENT (lists);
af45e3b0 247 while (1) {
1e6808ea 248 if (SCM_NULLP (lists)) {
af45e3b0
DH
249 return SCM_EOL;
250 } else {
1e6808ea
MG
251 SCM arg = SCM_CAR (lists);
252 lists = SCM_CDR (lists);
253 if (SCM_NULLP (lists)) {
af45e3b0
DH
254 return arg;
255 } else if (!SCM_NULLP (arg)) {
256 SCM_VALIDATE_CONS (SCM_ARG1, arg);
1e6808ea 257 SCM_SETCDR (scm_last_pair (arg), scm_append_x (lists));
af45e3b0
DH
258 return arg;
259 }
260 }
261 }
0f2d19dd 262}
1bbd0b84 263#undef FUNC_NAME
0f2d19dd
JB
264
265
3b3b36dd 266SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0,
e1385ffc 267 (SCM lst),
b380b885
MD
268 "Return a pointer to the last pair in @var{lst}, signalling an error if\n"
269 "@var{lst} is circular.")
1bbd0b84 270#define FUNC_NAME s_scm_last_pair
df13742c 271{
e1385ffc
GB
272 SCM tortoise = lst;
273 SCM hare = lst;
0f2d19dd 274
e1385ffc 275 if (SCM_NULLP (lst))
df13742c
JB
276 return SCM_EOL;
277
e1385ffc
GB
278 SCM_VALIDATE_CONS (SCM_ARG1, lst);
279 do {
280 SCM ahead = SCM_CDR(hare);
281 if (SCM_NCONSP(ahead)) return hare;
282 hare = ahead;
283 ahead = SCM_CDR(hare);
284 if (SCM_NCONSP(ahead)) return hare;
285 hare = ahead;
286 tortoise = SCM_CDR(tortoise);
df13742c 287 }
fbd485ba 288 while (! SCM_EQ_P (hare, tortoise));
5d2d2ffc 289 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
df13742c 290}
1bbd0b84 291#undef FUNC_NAME
df13742c
JB
292
293\f
294/* reversing lists */
0f2d19dd 295
a1ec6916 296SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0,
e1385ffc 297 (SCM lst),
5352393c
MG
298 "Return a new list that contains the elements of @var{lst} but\n"
299 "in reverse order.")
e1385ffc
GB
300#define FUNC_NAME s_scm_reverse
301{
302 SCM result = SCM_EOL;
303 SCM tortoise = lst;
304 SCM hare = lst;
305
306 do {
307 if (SCM_NULLP(hare)) return result;
308 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
309 result = scm_cons (SCM_CAR (hare), result);
310 hare = SCM_CDR (hare);
311 if (SCM_NULLP(hare)) return result;
312 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
313 result = scm_cons (SCM_CAR (hare), result);
314 hare = SCM_CDR (hare);
315 tortoise = SCM_CDR (tortoise);
316 }
fbd485ba 317 while (! SCM_EQ_P (hare, tortoise));
5d2d2ffc 318 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
e1385ffc
GB
319}
320#undef FUNC_NAME
321
322SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0,
323 (SCM lst, SCM new_tail),
7a095584
NJ
324 "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r5rs,\n"
325 "The Revised^5 Report on Scheme}). The cdr of each cell in @var{lst} is\n"
b380b885
MD
326 "modified to point to the previous list element. Return a pointer to the\n"
327 "head of the reversed list.\n\n"
328 "Caveat: because the list is modified in place, the tail of the original\n"
329 "list now becomes its head, and the head of the original list now becomes\n"
330 "the tail. Therefore, the @var{lst} symbol to which the head of the\n"
331 "original list was bound now points to the tail. To ensure that the head\n"
332 "of the modified list is not lost, it is wise to save the return value of\n"
333 "@code{reverse!}")
1bbd0b84 334#define FUNC_NAME s_scm_reverse_x
0f2d19dd 335{
e39c3de4 336 SCM_VALIDATE_LIST (1, lst);
3946f0de
MD
337 if (SCM_UNBNDP (new_tail))
338 new_tail = SCM_EOL;
339 else
e39c3de4 340 SCM_VALIDATE_LIST (2, new_tail);
0f2d19dd 341
e1385ffc 342 while (SCM_NNULLP (lst))
3946f0de 343 {
e1385ffc
GB
344 SCM old_tail = SCM_CDR (lst);
345 SCM_SETCDR (lst, new_tail);
346 new_tail = lst;
347 lst = old_tail;
3946f0de
MD
348 }
349 return new_tail;
0f2d19dd 350}
1bbd0b84 351#undef FUNC_NAME
0f2d19dd 352
0f2d19dd 353\f
685c0d71 354
df13742c 355/* indexing lists by element number */
0f2d19dd 356
3b3b36dd 357SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0,
685c0d71 358 (SCM list, SCM k),
5352393c 359 "Return the @var{k}th element from @var{list}.")
1bbd0b84
GB
360#define FUNC_NAME s_scm_list_ref
361{
685c0d71 362 SCM lst = list;
c014a02e 363 unsigned long int i;
3b3b36dd 364 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
685c0d71
DH
365 while (SCM_CONSP (lst)) {
366 if (i == 0)
367 return SCM_CAR (lst);
368 else {
369 --i;
370 lst = SCM_CDR (lst);
371 }
372 };
373 if (SCM_NULLP (lst))
374 SCM_OUT_OF_RANGE (2, k);
375 else
376 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 377}
1bbd0b84 378#undef FUNC_NAME
0f2d19dd 379
685c0d71 380
3b3b36dd 381SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0,
685c0d71
DH
382 (SCM list, SCM k, SCM val),
383 "Set the @var{k}th element of @var{list} to @var{val}.")
1bbd0b84
GB
384#define FUNC_NAME s_scm_list_set_x
385{
685c0d71 386 SCM lst = list;
c014a02e 387 unsigned long int i;
3b3b36dd 388 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
685c0d71
DH
389 while (SCM_CONSP (lst)) {
390 if (i == 0) {
391 SCM_SETCAR (lst, val);
392 return val;
393 } else {
394 --i;
395 lst = SCM_CDR (lst);
396 }
397 };
398 if (SCM_NULLP (lst))
399 SCM_OUT_OF_RANGE (2, k);
400 else
401 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 402}
1bbd0b84 403#undef FUNC_NAME
0f2d19dd
JB
404
405
1bbd0b84
GB
406SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail);
407
3b3b36dd 408SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0,
1bbd0b84 409 (SCM lst, SCM k),
872e0c72 410 "@deffnx primitive list-cdr-ref lst k\n"
b380b885
MD
411 "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n"
412 "The first element of the list is considered to be element 0.\n\n"
872e0c72 413 "@code{list-tail} and @code{list-cdr-ref} are identical. It may help to\n"
b380b885
MD
414 "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n"
415 "or returning the results of cdring @var{k} times down @var{lst}.")
1bbd0b84 416#define FUNC_NAME s_scm_list_tail
df13742c 417{
c014a02e 418 register long i;
3b3b36dd 419 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
df13742c 420 while (i-- > 0) {
3b3b36dd 421 SCM_VALIDATE_CONS (1,lst);
df13742c
JB
422 lst = SCM_CDR(lst);
423 }
424 return lst;
425}
1bbd0b84 426#undef FUNC_NAME
df13742c 427
0f2d19dd 428
3b3b36dd 429SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0,
685c0d71
DH
430 (SCM list, SCM k, SCM val),
431 "Set the @var{k}th cdr of @var{list} to @var{val}.")
1bbd0b84
GB
432#define FUNC_NAME s_scm_list_cdr_set_x
433{
685c0d71 434 SCM lst = list;
c014a02e 435 unsigned long int i;
3b3b36dd 436 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
685c0d71
DH
437 while (SCM_CONSP (lst)) {
438 if (i == 0) {
439 SCM_SETCDR (lst, val);
440 return val;
441 } else {
442 --i;
443 lst = SCM_CDR (lst);
444 }
445 };
446 if (SCM_NULLP (lst))
447 SCM_OUT_OF_RANGE (2, k);
448 else
449 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 450}
1bbd0b84 451#undef FUNC_NAME
0f2d19dd
JB
452
453
454\f
df13742c 455/* copying lists, perhaps partially */
0f2d19dd 456
3b3b36dd 457SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0,
1bbd0b84 458 (SCM lst, SCM k),
b380b885
MD
459 "Copy the first @var{k} elements from @var{lst} into a new list, and\n"
460 "return it.")
1bbd0b84 461#define FUNC_NAME s_scm_list_head
0f2d19dd
JB
462{
463 SCM answer;
464 SCM * pos;
c014a02e 465 register long i;
0f2d19dd 466
3b3b36dd 467 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
0f2d19dd
JB
468 answer = SCM_EOL;
469 pos = &answer;
0f2d19dd
JB
470 while (i-- > 0)
471 {
3b3b36dd 472 SCM_VALIDATE_CONS (1,lst);
0f2d19dd 473 *pos = scm_cons (SCM_CAR (lst), SCM_EOL);
25d8012c 474 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
475 lst = SCM_CDR(lst);
476 }
477 return answer;
478}
1bbd0b84 479#undef FUNC_NAME
0f2d19dd
JB
480
481
a1ec6916 482SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0,
1bbd0b84 483 (SCM lst),
b380b885 484 "Return a (newly-created) copy of @var{lst}.")
1bbd0b84 485#define FUNC_NAME s_scm_list_copy
df13742c
JB
486{
487 SCM newlst;
488 SCM * fill_here;
489 SCM from_here;
490
5d6bb349
KN
491 SCM_VALIDATE_LIST (1, lst);
492
df13742c
JB
493 newlst = SCM_EOL;
494 fill_here = &newlst;
495 from_here = lst;
496
0c95b57d 497 while (SCM_CONSP (from_here))
df13742c
JB
498 {
499 SCM c;
500 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
501 *fill_here = c;
25d8012c 502 fill_here = SCM_CDRLOC (c);
df13742c
JB
503 from_here = SCM_CDR (from_here);
504 }
505 return newlst;
506}
1bbd0b84 507#undef FUNC_NAME
df13742c 508
0f2d19dd 509\f
df13742c
JB
510/* membership tests (memq, memv, etc.) */
511
daa6ba18
DH
512#if SCM_DEBUG_DEPRECATED == 0
513
a1ec6916 514SCM_DEFINE (scm_sloppy_memq, "sloppy-memq", 2, 0, 0,
1bbd0b84 515 (SCM x, SCM lst),
b450f070
GB
516 "This procedure behaves like @code{memq}, but does no type or error checking.\n"
517 "Its use is recommended only in writing Guile internals,\n"
518 "not for high-level Scheme programs.")
1bbd0b84 519#define FUNC_NAME s_scm_sloppy_memq
0f2d19dd 520{
0c95b57d 521 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 522 {
fbd485ba 523 if (SCM_EQ_P (SCM_CAR (lst), x))
0f2d19dd
JB
524 return lst;
525 }
526 return lst;
527}
1bbd0b84 528#undef FUNC_NAME
0f2d19dd
JB
529
530
a1ec6916 531SCM_DEFINE (scm_sloppy_memv, "sloppy-memv", 2, 0, 0,
1bbd0b84 532 (SCM x, SCM lst),
b450f070
GB
533 "This procedure behaves like @code{memv}, but does no type or error checking.\n"
534 "Its use is recommended only in writing Guile internals,\n"
535 "not for high-level Scheme programs.")
1bbd0b84 536#define FUNC_NAME s_scm_sloppy_memv
0f2d19dd 537{
0c95b57d 538 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 539 {
fbd485ba 540 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (lst), x)))
0f2d19dd
JB
541 return lst;
542 }
543 return lst;
544}
1bbd0b84 545#undef FUNC_NAME
0f2d19dd
JB
546
547
a1ec6916 548SCM_DEFINE (scm_sloppy_member, "sloppy-member", 2, 0, 0,
1bbd0b84 549 (SCM x, SCM lst),
b450f070
GB
550 "This procedure behaves like @code{member}, but does no type or error checking.\n"
551 "Its use is recommended only in writing Guile internals,\n"
552 "not for high-level Scheme programs.")
1bbd0b84 553#define FUNC_NAME s_scm_sloppy_member
0f2d19dd 554{
0c95b57d 555 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 556 {
fbd485ba 557 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (lst), x)))
0f2d19dd
JB
558 return lst;
559 }
560 return lst;
561}
1bbd0b84 562#undef FUNC_NAME
0f2d19dd 563
daa6ba18 564#endif /* DEPRECATED */
0f2d19dd 565
79a3dafe
DH
566/* The function scm_c_memq returns the first sublist of list whose car is
567 * 'eq?' obj, where the sublists of list are the non-empty lists returned by
568 * (list-tail list k) for k less than the length of list. If obj does not
1e6808ea 569 * occur in list, then #f (not the empty list) is returned.
79a3dafe
DH
570 * List must be a proper list, otherwise scm_c_memq may crash or loop
571 * endlessly.
572 */
573SCM
574scm_c_memq (SCM obj, SCM list)
575{
576 for (; !SCM_NULLP (list); list = SCM_CDR (list))
577 {
578 if (SCM_EQ_P (SCM_CAR (list), obj))
579 return list;
580 }
581 return SCM_BOOL_F;
582}
583
584
3b3b36dd 585SCM_DEFINE (scm_memq, "memq", 2, 0, 0,
1bbd0b84 586 (SCM x, SCM lst),
5352393c
MG
587 "Return the first sublist of @var{lst} whose car is @code{eq?}\n"
588 "to @var{x} where the sublists of @var{lst} are the non-empty\n"
589 "lists returned by @code{(list-tail @var{lst} @var{k})} for\n"
590 "@var{k} less than the length of @var{lst}. If @var{x} does not\n"
591 "occur in @var{lst}, then @code{#f} (not the empty list) is\n"
592 "returned.")
1bbd0b84 593#define FUNC_NAME s_scm_memq
0f2d19dd 594{
daa6ba18 595 SCM_VALIDATE_LIST (2, lst);
79a3dafe 596 return scm_c_memq (x, lst);
0f2d19dd 597}
1bbd0b84 598#undef FUNC_NAME
0f2d19dd
JB
599
600
601
3b3b36dd 602SCM_DEFINE (scm_memv, "memv", 2, 0, 0,
1bbd0b84 603 (SCM x, SCM lst),
5352393c
MG
604 "Return the first sublist of @var{lst} whose car is @code{eqv?}\n"
605 "to @var{x} where the sublists of @var{lst} are the non-empty\n"
606 "lists returned by @code{(list-tail @var{lst} @var{k})} for\n"
607 "@var{k} less than the length of @var{lst}. If @var{x} does not\n"
608 "occur in @var{lst}, then @code{#f} (not the empty list) is\n"
609 "returned.")
1bbd0b84 610#define FUNC_NAME s_scm_memv
0f2d19dd 611{
daa6ba18
DH
612 SCM_VALIDATE_LIST (2, lst);
613 for (; !SCM_NULLP (lst); lst = SCM_CDR (lst))
614 {
615 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (lst), x)))
616 return lst;
617 }
618 return SCM_BOOL_F;
0f2d19dd 619}
1bbd0b84 620#undef FUNC_NAME
0f2d19dd
JB
621
622
3b3b36dd 623SCM_DEFINE (scm_member, "member", 2, 0, 0,
1bbd0b84 624 (SCM x, SCM lst),
5352393c
MG
625 "Return the first sublist of @var{lst} whose car is\n"
626 "@code{equal?} to @var{x} where the sublists of @var{lst} are\n"
627 "the non-empty lists returned by @code{(list-tail @var{lst}\n"
628 "@var{k})} for @var{k} less than the length of @var{lst}. If\n"
629 "@var{x} does not occur in @var{lst}, then @code{#f} (not the\n"
630 "empty list) is returned.")
1bbd0b84 631#define FUNC_NAME s_scm_member
0f2d19dd 632{
daa6ba18
DH
633 SCM_VALIDATE_LIST (2, lst);
634 for (; !SCM_NULLP (lst); lst = SCM_CDR (lst))
635 {
636 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (lst), x)))
637 return lst;
638 }
639 return SCM_BOOL_F;
0f2d19dd 640}
1bbd0b84 641#undef FUNC_NAME
0f2d19dd
JB
642
643
644\f
df13742c 645/* deleting elements from a list (delq, etc.) */
0f2d19dd 646
3b3b36dd 647SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0,
1bbd0b84 648 (SCM item, SCM lst),
b380b885
MD
649 "@deffnx primitive delv! item lst\n"
650 "@deffnx primitive delete! item lst\n"
651 "These procedures are destructive versions of @code{delq}, @code{delv}\n"
652 "and @code{delete}: they modify the pointers in the existing @var{lst}\n"
653 "rather than creating a new list. Caveat evaluator: Like other\n"
654 "destructive list functions, these functions cannot modify the binding of\n"
655 "@var{lst}, and so cannot be used to delete the first element of\n"
656 "@var{lst} destructively.")
1bbd0b84 657#define FUNC_NAME s_scm_delq_x
0f2d19dd 658{
164271a1
JB
659 SCM walk;
660 SCM *prev;
0f2d19dd 661
164271a1 662 for (prev = &lst, walk = lst;
0c95b57d 663 SCM_CONSP (walk);
164271a1 664 walk = SCM_CDR (walk))
0f2d19dd 665 {
fbd485ba 666 if (SCM_EQ_P (SCM_CAR (walk), item))
164271a1
JB
667 *prev = SCM_CDR (walk);
668 else
669 prev = SCM_CDRLOC (walk);
0f2d19dd 670 }
164271a1
JB
671
672 return lst;
0f2d19dd 673}
1bbd0b84 674#undef FUNC_NAME
0f2d19dd
JB
675
676
3b3b36dd 677SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0,
5352393c
MG
678 (SCM item, SCM lst),
679 "Destructively remove all elements from @var{lst} that are\n"
680 "@code{eqv?} to @var{item}.")
1bbd0b84 681#define FUNC_NAME s_scm_delv_x
0f2d19dd 682{
164271a1
JB
683 SCM walk;
684 SCM *prev;
0f2d19dd 685
164271a1 686 for (prev = &lst, walk = lst;
0c95b57d 687 SCM_CONSP (walk);
164271a1 688 walk = SCM_CDR (walk))
0f2d19dd 689 {
fbd485ba 690 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (walk), item)))
164271a1
JB
691 *prev = SCM_CDR (walk);
692 else
693 prev = SCM_CDRLOC (walk);
0f2d19dd 694 }
164271a1
JB
695
696 return lst;
0f2d19dd 697}
1bbd0b84 698#undef FUNC_NAME
0f2d19dd
JB
699
700
701
3b3b36dd 702SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0,
5352393c
MG
703 (SCM item, SCM lst),
704 "Destructively remove all elements from @var{lst} that are\n"
705 "@code{equal?} to @var{item}.")
1bbd0b84 706#define FUNC_NAME s_scm_delete_x
0f2d19dd 707{
164271a1
JB
708 SCM walk;
709 SCM *prev;
0f2d19dd 710
164271a1 711 for (prev = &lst, walk = lst;
0c95b57d 712 SCM_CONSP (walk);
164271a1 713 walk = SCM_CDR (walk))
0f2d19dd 714 {
fbd485ba 715 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (walk), item)))
164271a1
JB
716 *prev = SCM_CDR (walk);
717 else
718 prev = SCM_CDRLOC (walk);
0f2d19dd 719 }
164271a1
JB
720
721 return lst;
0f2d19dd 722}
1bbd0b84 723#undef FUNC_NAME
0f2d19dd
JB
724
725
726\f
727
0f2d19dd 728
a1ec6916 729SCM_DEFINE (scm_delq, "delq", 2, 0, 0,
1bbd0b84 730 (SCM item, SCM lst),
5352393c
MG
731 "Return a newly-created copy of @var{lst} with elements\n"
732 "@code{eq?} to @var{item} removed. This procedure mirrors\n"
733 "@code{memq}: @code{delq} compares elements of @var{lst} against\n"
734 "@var{item} with @code{eq?}.")
1bbd0b84 735#define FUNC_NAME s_scm_delq
0f2d19dd 736{
1bbd0b84 737 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
738 return scm_delq_x (item, copy);
739}
1bbd0b84 740#undef FUNC_NAME
0f2d19dd 741
a1ec6916 742SCM_DEFINE (scm_delv, "delv", 2, 0, 0,
1bbd0b84 743 (SCM item, SCM lst),
5352393c
MG
744 "Return a newly-created copy of @var{lst} with elements\n"
745 "@code{eqv?} to @var{item} removed. This procedure mirrors\n"
746 "@code{memv}: @code{delv} compares elements of @var{lst} against\n"
747 "@var{item} with @code{eqv?}.")
1bbd0b84 748#define FUNC_NAME s_scm_delv
0f2d19dd 749{
1bbd0b84 750 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
751 return scm_delv_x (item, copy);
752}
1bbd0b84 753#undef FUNC_NAME
0f2d19dd 754
a1ec6916 755SCM_DEFINE (scm_delete, "delete", 2, 0, 0,
1bbd0b84 756 (SCM item, SCM lst),
5352393c
MG
757 "Return a newly-created copy of @var{lst} with elements\n"
758 "@code{equal?} to @var{item} removed. This procedure mirrors\n"
759 "@code{member}: @code{delete} compares elements of @var{lst}\n"
760 "against @var{item} with @code{equal?}.")
1bbd0b84 761#define FUNC_NAME s_scm_delete
0f2d19dd 762{
1bbd0b84 763 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
764 return scm_delete_x (item, copy);
765}
1bbd0b84 766#undef FUNC_NAME
0f2d19dd
JB
767
768
3b3b36dd 769SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0,
1bbd0b84 770 (SCM item, SCM lst),
5352393c
MG
771 "Like @code{delq!}, but only deletes the first occurrence of\n"
772 "@var{item} from @var{lst}. Tests for equality using\n"
773 "@code{eq?}. See also @code{delv1!} and @code{delete1!}.")
1bbd0b84 774#define FUNC_NAME s_scm_delq1_x
82dc9f57
MD
775{
776 SCM walk;
777 SCM *prev;
778
779 for (prev = &lst, walk = lst;
0c95b57d 780 SCM_CONSP (walk);
82dc9f57
MD
781 walk = SCM_CDR (walk))
782 {
fbd485ba 783 if (SCM_EQ_P (SCM_CAR (walk), item))
82dc9f57
MD
784 {
785 *prev = SCM_CDR (walk);
786 break;
787 }
788 else
789 prev = SCM_CDRLOC (walk);
790 }
791
792 return lst;
793}
1bbd0b84 794#undef FUNC_NAME
82dc9f57
MD
795
796
3b3b36dd 797SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0,
8507b88c 798 (SCM item, SCM lst),
5352393c
MG
799 "Like @code{delv!}, but only deletes the first occurrence of\n"
800 "@var{item} from @var{lst}. Tests for equality using\n"
801 "@code{eqv?}. See also @code{delq1!} and @code{delete1!}.")
1bbd0b84 802#define FUNC_NAME s_scm_delv1_x
82dc9f57
MD
803{
804 SCM walk;
805 SCM *prev;
806
807 for (prev = &lst, walk = lst;
0c95b57d 808 SCM_CONSP (walk);
82dc9f57
MD
809 walk = SCM_CDR (walk))
810 {
fbd485ba 811 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (walk), item)))
82dc9f57
MD
812 {
813 *prev = SCM_CDR (walk);
814 break;
815 }
816 else
817 prev = SCM_CDRLOC (walk);
818 }
819
820 return lst;
821}
1bbd0b84 822#undef FUNC_NAME
82dc9f57
MD
823
824
3b3b36dd 825SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
8507b88c 826 (SCM item, SCM lst),
5352393c
MG
827 "Like @code{delete!}, but only deletes the first occurrence of\n"
828 "@var{item} from @var{lst}. Tests for equality using\n"
829 "@code{equal?}. See also @code{delq1!} and @code{delv1!}.")
1bbd0b84 830#define FUNC_NAME s_scm_delete1_x
82dc9f57
MD
831{
832 SCM walk;
833 SCM *prev;
834
835 for (prev = &lst, walk = lst;
0c95b57d 836 SCM_CONSP (walk);
82dc9f57
MD
837 walk = SCM_CDR (walk))
838 {
fbd485ba 839 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (walk), item)))
82dc9f57
MD
840 {
841 *prev = SCM_CDR (walk);
842 break;
843 }
844 else
845 prev = SCM_CDRLOC (walk);
846 }
847
848 return lst;
849}
1bbd0b84 850#undef FUNC_NAME
82dc9f57
MD
851
852
0f2d19dd 853\f
0f2d19dd
JB
854void
855scm_init_list ()
0f2d19dd 856{
8dc9439f 857#ifndef SCM_MAGIC_SNARFER
a0599745 858#include "libguile/list.x"
8dc9439f 859#endif
0f2d19dd 860}
89e00824
ML
861
862/*
863 Local Variables:
864 c-file-style: "gnu"
865 End:
866*/