alist.c 10 KB

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