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