alist.c 12 KB

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