* Some more work to get rid of SCM_LENGTH
[bpt/guile.git] / libguile / alist.c
CommitLineData
e282f286 1/* Copyright (C) 1995, 96, 97, 98, 99, 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
JB
45\f
46#include <stdio.h>
a0599745
MD
47#include "libguile/_scm.h"
48#include "libguile/eq.h"
49#include "libguile/list.h"
20e6290e 50
a0599745
MD
51#include "libguile/validate.h"
52#include "libguile/alist.h"
0f2d19dd
JB
53
54\f
55
3b3b36dd 56SCM_DEFINE (scm_acons, "acons", 3, 0, 0,
0b5f3f34 57 (SCM key, SCM value, SCM alist),
b380b885
MD
58 "Adds a new key-value pair to @var{alist}. A new pair is\n"
59 "created whose car is @var{key} and whose cdr is @var{value}, and the\n"
60 "pair is consed onto @var{alist}, and the new list is returned. This\n"
61 "function is @emph{not} destructive; @var{alist} is not modified.")
1bbd0b84 62#define FUNC_NAME s_scm_acons
0f2d19dd 63{
0b5f3f34
GB
64 SCM pair;
65 SCM head;
66
67 SCM_NEWCELL (pair);
665aeda3
DH
68 SCM_SET_CELL_OBJECT_0 (pair, key);
69 SCM_SET_CELL_OBJECT_1 (pair, value);
0b5f3f34
GB
70
71 SCM_NEWCELL (head);
665aeda3
DH
72 SCM_SET_CELL_OBJECT_0 (head, pair);
73 SCM_SET_CELL_OBJECT_1 (head, alist);
0b5f3f34
GB
74
75 return head;
0f2d19dd 76}
1bbd0b84 77#undef FUNC_NAME
0f2d19dd
JB
78
79\f
80
a1ec6916 81SCM_DEFINE (scm_sloppy_assq, "sloppy-assq", 2, 0, 0,
0b5f3f34 82 (SCM key, SCM alist),
b380b885
MD
83 "Behaves like @code{assq} but does not do any error checking.\n"
84 "Recommended only for use in Guile internals.")
1bbd0b84 85#define FUNC_NAME s_scm_sloppy_assq
0f2d19dd 86{
0c95b57d 87 for (; SCM_CONSP (alist); alist = SCM_CDR (alist))
0f2d19dd 88 {
2de257bd 89 SCM tmp = SCM_CAR (alist);
fbd485ba 90 if (SCM_CONSP (tmp) && SCM_EQ_P (SCM_CAR (tmp), key))
cf18adf0 91 return tmp;
0f2d19dd
JB
92 }
93 return SCM_BOOL_F;
94}
1bbd0b84 95#undef FUNC_NAME
0f2d19dd
JB
96
97
98
a1ec6916 99SCM_DEFINE (scm_sloppy_assv, "sloppy-assv", 2, 0, 0,
0b5f3f34 100 (SCM key, SCM alist),
b380b885
MD
101 "Behaves like @code{assv} but does not do any error checking.\n"
102 "Recommended only for use in Guile internals.")
1bbd0b84 103#define FUNC_NAME s_scm_sloppy_assv
0f2d19dd 104{
0c95b57d 105 for (; SCM_CONSP (alist); alist = SCM_CDR (alist))
0f2d19dd 106 {
2de257bd 107 SCM tmp = SCM_CAR (alist);
0b5f3f34
GB
108 if (SCM_CONSP (tmp)
109 && SCM_NFALSEP (scm_eqv_p (SCM_CAR (tmp), key)))
cf18adf0 110 return tmp;
0f2d19dd
JB
111 }
112 return SCM_BOOL_F;
113}
1bbd0b84 114#undef FUNC_NAME
0f2d19dd
JB
115
116
a1ec6916 117SCM_DEFINE (scm_sloppy_assoc, "sloppy-assoc", 2, 0, 0,
0b5f3f34 118 (SCM key, SCM alist),
b380b885
MD
119 "Behaves like @code{assoc} but does not do any error checking.\n"
120 "Recommended only for use in Guile internals.")
1bbd0b84 121#define FUNC_NAME s_scm_sloppy_assoc
0f2d19dd 122{
0c95b57d 123 for (; SCM_CONSP (alist); alist = SCM_CDR (alist))
0f2d19dd 124 {
2de257bd 125 SCM tmp = SCM_CAR (alist);
0b5f3f34
GB
126 if (SCM_CONSP (tmp)
127 && SCM_NFALSEP (scm_equal_p (SCM_CAR (tmp), key)))
cf18adf0 128 return tmp;
0f2d19dd
JB
129 }
130 return SCM_BOOL_F;
131}
1bbd0b84 132#undef FUNC_NAME
0f2d19dd
JB
133
134
135\f
136
3b3b36dd 137SCM_DEFINE (scm_assq, "assq", 2, 0, 0,
0b5f3f34 138 (SCM key, SCM alist),
b380b885
MD
139 "@deffnx primitive assv key alist\n"
140 "@deffnx primitive assoc key alist\n"
141 "Fetches the entry in @var{alist} that is associated with @var{key}. To\n"
142 "decide whether the argument @var{key} matches a particular entry in\n"
143 "@var{alist}, @code{assq} compares keys with @code{eq?}, @code{assv}\n"
144 "uses @code{eqv?} and @code{assoc} uses @code{equal?}. If @var{key}\n"
145 "cannot be found in @var{alist} (according to whichever equality\n"
146 "predicate is in use), then @code{#f} is returned. These functions\n"
147 "return the entire alist entry found (i.e. both the key and the value).")
1bbd0b84 148#define FUNC_NAME s_scm_assq
0f2d19dd 149{
1aa621a3
MD
150 SCM ls = alist;
151 for (; SCM_CONSP (ls); ls = SCM_CDR (ls))
e1385ffc 152 {
1aa621a3
MD
153 SCM tmp = SCM_CAR (ls);
154 SCM_ASSERT_TYPE (SCM_CONSP (tmp), alist, SCM_ARG2, FUNC_NAME,
155 "association list");
fbd485ba 156 if (SCM_EQ_P (SCM_CAR (tmp), key))
2de257bd 157 return tmp;
e1385ffc 158 }
1aa621a3
MD
159 SCM_ASSERT_TYPE (SCM_NULLP (ls), alist, SCM_ARG2, FUNC_NAME,
160 "association list");
1bbd0b84 161 return SCM_BOOL_F;
0f2d19dd 162}
1bbd0b84 163#undef FUNC_NAME
0f2d19dd
JB
164
165
3b3b36dd 166SCM_DEFINE (scm_assv, "assv", 2, 0, 0,
0b5f3f34 167 (SCM key, SCM alist),
b380b885 168 "Behaves like @code{assq} but uses @code{eqv?} for key comparison.")
1bbd0b84 169#define FUNC_NAME s_scm_assv
0f2d19dd 170{
1aa621a3
MD
171 SCM ls = alist;
172 for(; SCM_CONSP (ls); ls = SCM_CDR (ls))
e1385ffc 173 {
1aa621a3
MD
174 SCM tmp = SCM_CAR (ls);
175 SCM_ASSERT_TYPE (SCM_CONSP (tmp), alist, SCM_ARG2, FUNC_NAME,
176 "association list");
2de257bd
MD
177 if (SCM_NFALSEP (scm_eqv_p (SCM_CAR (tmp), key)))
178 return tmp;
e1385ffc 179 }
1aa621a3
MD
180 SCM_ASSERT_TYPE (SCM_NULLP (ls), alist, SCM_ARG2, FUNC_NAME,
181 "association list");
0f2d19dd
JB
182 return SCM_BOOL_F;
183}
1bbd0b84 184#undef FUNC_NAME
0f2d19dd
JB
185
186
3b3b36dd 187SCM_DEFINE (scm_assoc, "assoc", 2, 0, 0,
0b5f3f34 188 (SCM key, SCM alist),
b380b885 189 "Behaves like @code{assq} but uses @code{equal?} for key comparison.")
1bbd0b84 190#define FUNC_NAME s_scm_assoc
0f2d19dd 191{
1aa621a3
MD
192 SCM ls = alist;
193 for(; SCM_CONSP (ls); ls = SCM_CDR (ls))
e1385ffc 194 {
1aa621a3
MD
195 SCM tmp = SCM_CAR (ls);
196 SCM_ASSERT_TYPE (SCM_CONSP (tmp), alist, SCM_ARG2, FUNC_NAME,
197 "association list");
2de257bd
MD
198 if (SCM_NFALSEP (scm_equal_p (SCM_CAR (tmp), key)))
199 return tmp;
e1385ffc 200 }
1aa621a3
MD
201 SCM_ASSERT_TYPE (SCM_NULLP (ls), alist, SCM_ARG2, FUNC_NAME,
202 "association list");
1bbd0b84 203 return SCM_BOOL_F;
0f2d19dd 204}
1bbd0b84 205#undef FUNC_NAME
0f2d19dd
JB
206
207
208\f
209
d1ca2c64
DH
210/* Dirk:API2.0:: We should not return #f if the key was not found. In the
211 * current solution we can not distinguish between finding a (key . #f) pair
212 * and not finding the key at all.
213 *
214 * Possible alternative solutions:
215 * 1) Remove assq-ref from the API: assq is sufficient.
216 * 2) Signal an error (what error type?) if the key is not found.
217 * 3) provide an additional 'default' parameter.
218 * 3.1) The default parameter is mandatory.
219 * 3.2) The default parameter is optional, but if no default is given and
220 * the key is not found, signal an error (what error type?).
221 */
a1ec6916 222SCM_DEFINE (scm_assq_ref, "assq-ref", 2, 0, 0,
1bbd0b84 223 (SCM alist, SCM key),
b380b885
MD
224 "@deffnx primitive assv-ref alist key\n"
225 "@deffnx primitive assoc-ref alist key\n"
226 "Like @code{assq}, @code{assv} and @code{assoc}, except that only the\n"
227 "value associated with @var{key} in @var{alist} is returned. These\n"
228 "functions are equivalent to\n\n"
229 "@lisp\n"
230 "(let ((ent (@var{associator} @var{key} @var{alist})))\n"
231 " (and ent (cdr ent)))\n"
232 "@end lisp\n\n"
233 "where @var{associator} is one of @code{assq}, @code{assv} or @code{assoc}.")
1bbd0b84 234#define FUNC_NAME s_scm_assq_ref
0f2d19dd
JB
235{
236 SCM handle;
237
238 handle = scm_sloppy_assq (key, alist);
0c95b57d 239 if (SCM_CONSP (handle))
0f2d19dd
JB
240 {
241 return SCM_CDR (handle);
242 }
243 return SCM_BOOL_F;
244}
1bbd0b84 245#undef FUNC_NAME
0f2d19dd
JB
246
247
a1ec6916 248SCM_DEFINE (scm_assv_ref, "assv-ref", 2, 0, 0,
1bbd0b84 249 (SCM alist, SCM key),
b380b885 250 "Behaves like @code{assq-ref} but uses @code{eqv?} for key comparison.")
1bbd0b84 251#define FUNC_NAME s_scm_assv_ref
0f2d19dd
JB
252{
253 SCM handle;
254
255 handle = scm_sloppy_assv (key, alist);
0c95b57d 256 if (SCM_CONSP (handle))
0f2d19dd
JB
257 {
258 return SCM_CDR (handle);
259 }
260 return SCM_BOOL_F;
261}
1bbd0b84 262#undef FUNC_NAME
0f2d19dd
JB
263
264
a1ec6916 265SCM_DEFINE (scm_assoc_ref, "assoc-ref", 2, 0, 0,
1bbd0b84 266 (SCM alist, SCM key),
b380b885 267 "Behaves like @code{assq-ref} but uses @code{equal?} for key comparison.")
1bbd0b84 268#define FUNC_NAME s_scm_assoc_ref
0f2d19dd
JB
269{
270 SCM handle;
271
272 handle = scm_sloppy_assoc (key, alist);
0c95b57d 273 if (SCM_CONSP (handle))
0f2d19dd
JB
274 {
275 return SCM_CDR (handle);
276 }
277 return SCM_BOOL_F;
278}
1bbd0b84 279#undef FUNC_NAME
0f2d19dd
JB
280
281
282
283\f
284
285
a1ec6916 286SCM_DEFINE (scm_assq_set_x, "assq-set!", 3, 0, 0,
1bbd0b84 287 (SCM alist, SCM key, SCM val),
b380b885
MD
288 "@deffnx primitive assv-set! alist key value\n"
289 "@deffnx primitive assoc-set! alist key value\n"
290 "Reassociate @var{key} in @var{alist} with @var{value}: find any existing\n"
291 "@var{alist} entry for @var{key} and associate it with the new\n"
292 "@var{value}. If @var{alist} does not contain an entry for @var{key},\n"
293 "add a new one. Return the (possibly new) alist.\n\n"
294 "These functions do not attempt to verify the structure of @var{alist},\n"
295 "and so may cause unusual results if passed an object that is not an\n"
296 "association list.")
1bbd0b84 297#define FUNC_NAME s_scm_assq_set_x
0f2d19dd
JB
298{
299 SCM handle;
300
301 handle = scm_sloppy_assq (key, alist);
0c95b57d 302 if (SCM_CONSP (handle))
0f2d19dd
JB
303 {
304 SCM_SETCDR (handle, val);
305 return alist;
306 }
307 else
308 return scm_acons (key, val, alist);
309}
1bbd0b84 310#undef FUNC_NAME
0f2d19dd 311
a1ec6916 312SCM_DEFINE (scm_assv_set_x, "assv-set!", 3, 0, 0,
1bbd0b84 313 (SCM alist, SCM key, SCM val),
b380b885 314 "Behaves like @code{assq-set!} but uses @code{eqv?} for key comparison.")
1bbd0b84 315#define FUNC_NAME s_scm_assv_set_x
0f2d19dd
JB
316{
317 SCM handle;
318
319 handle = scm_sloppy_assv (key, alist);
0c95b57d 320 if (SCM_CONSP (handle))
0f2d19dd
JB
321 {
322 SCM_SETCDR (handle, val);
323 return alist;
324 }
325 else
326 return scm_acons (key, val, alist);
327}
1bbd0b84 328#undef FUNC_NAME
0f2d19dd 329
a1ec6916 330SCM_DEFINE (scm_assoc_set_x, "assoc-set!", 3, 0, 0,
1bbd0b84 331 (SCM alist, SCM key, SCM val),
b380b885 332 "Behaves like @code{assq-set!} but uses @code{equal?} for key comparison.")
1bbd0b84 333#define FUNC_NAME s_scm_assoc_set_x
0f2d19dd
JB
334{
335 SCM handle;
336
337 handle = scm_sloppy_assoc (key, alist);
0c95b57d 338 if (SCM_CONSP (handle))
0f2d19dd
JB
339 {
340 SCM_SETCDR (handle, val);
341 return alist;
342 }
343 else
344 return scm_acons (key, val, alist);
345}
1bbd0b84 346#undef FUNC_NAME
0f2d19dd
JB
347
348
349\f
350
a1ec6916 351SCM_DEFINE (scm_assq_remove_x, "assq-remove!", 2, 0, 0,
1bbd0b84 352 (SCM alist, SCM key),
b380b885
MD
353 "@deffnx primitive assv-remove! alist key\n"
354 "@deffnx primitive assoc-remove! alist key\n"
623ada63 355 "Delete the first entry in @var{alist} associated with @var{key}, and return\n"
b380b885 356 "the resulting alist.")
1bbd0b84 357#define FUNC_NAME s_scm_assq_remove_x
0f2d19dd
JB
358{
359 SCM handle;
360
361 handle = scm_sloppy_assq (key, alist);
623ada63 362 if (SCM_CONSP (handle))
60e61f0a 363 alist = scm_delq1_x (handle, alist);
623ada63 364
5d253852 365 return alist;
0f2d19dd 366}
1bbd0b84 367#undef FUNC_NAME
0f2d19dd
JB
368
369
a1ec6916 370SCM_DEFINE (scm_assv_remove_x, "assv-remove!", 2, 0, 0,
1bbd0b84 371 (SCM alist, SCM key),
b380b885 372 "Behaves like @code{assq-remove!} but uses @code{eqv?} for key comparison.")
1bbd0b84 373#define FUNC_NAME s_scm_assv_remove_x
0f2d19dd
JB
374{
375 SCM handle;
376
377 handle = scm_sloppy_assv (key, alist);
623ada63 378 if (SCM_CONSP (handle))
60e61f0a 379 alist = scm_delq1_x (handle, alist);
623ada63 380
5d253852 381 return alist;
0f2d19dd 382}
1bbd0b84 383#undef FUNC_NAME
0f2d19dd
JB
384
385
a1ec6916 386SCM_DEFINE (scm_assoc_remove_x, "assoc-remove!", 2, 0, 0,
1bbd0b84 387 (SCM alist, SCM key),
b380b885 388 "Behaves like @code{assq-remove!} but uses @code{equal?} for key comparison.")
1bbd0b84 389#define FUNC_NAME s_scm_assoc_remove_x
0f2d19dd
JB
390{
391 SCM handle;
392
393 handle = scm_sloppy_assoc (key, alist);
623ada63 394 if (SCM_CONSP (handle))
60e61f0a 395 alist = scm_delq1_x (handle, alist);
623ada63 396
5d253852 397 return alist;
0f2d19dd 398}
1bbd0b84 399#undef FUNC_NAME
0f2d19dd
JB
400
401
402\f
403
404
1cc91f1b 405
0f2d19dd
JB
406void
407scm_init_alist ()
0f2d19dd 408{
a0599745 409#include "libguile/alist.x"
0f2d19dd
JB
410}
411
89e00824
ML
412
413/*
414 Local Variables:
415 c-file-style: "gnu"
416 End:
417*/