alist.c 11 KB

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