This is the mail archive of the
guile@sourceware.cygnus.com
mailing list for the Guile project.
patch for append
- To: Guile Mailing List <guile at sourceware dot cygnus dot com>
- Subject: patch for append
- From: Dirk Herrmann <dirk at ida dot ing dot tu-bs dot de>
- Date: Tue, 18 Jan 2000 17:15:55 +0100 (MET)
Hi!
Below is a patch for list.c which fixes the problem with circular lists
when given as parameters to append.
It also puts the documentation for append! at the proper place.
In this patch I decided to:
* keep the semantics (append) -> '(), although r4rs and r5rs are not
explicit about whether this is allowed.
* assume that a rest argument is always a proper list. I used SCM_NNULLP
as the predicate to figure out whether the end of the list is not
reached yet. Alternatively, SCM_CONSP could have been used. However,
SCM_NNULLP can be assumed to be faster, since it does not have to check
contents of the cell. If we can assume that the argument is a proper
list, both predicates lead to the same behaviour, but it is debatable
whether both of them reflect the semantics in the same way. Personally
I feel a little better with SCM_CONSP, but still decided to use
SCM_NNULLP, because the semantic difference is quite small and the
performance of SCM_NNULLP can be expected to be quite some better.
In case you feel bad about not typechecking the rest argument for being
a proper list, I think the best solution would be as a compile time
option, like defining DEBUG or something.
BTW: I signed the copyright assignment for the FSF and will put it into
the post box this evening.
Best regards,
Dirk Herrmann
RCS file: /cvs/guile/guile/guile-core/libguile/list.c,v
retrieving revision 1.28
diff -u -p -r1.28 list.c
--- list.c 2000/01/18 13:09:54 1.28
+++ list.c 2000/01/18 15:58:45
@@ -181,41 +181,56 @@ SCM_DEFINE (scm_length, "length", 1, 0,
SCM_DEFINE (scm_append, "append", 0, 0, 1,
(SCM args),
- "A destructive version of @code{append} (@pxref{Pairs and Lists,,,r4rs,\n"
- "The Revised^4 Report on Scheme}). The cdr field of each list's final\n"
- "pair is changed to point to the head of the next list, so no consing is\n"
- "performed. Return a pointer to the mutated list.")
+ "")
#define FUNC_NAME s_scm_append
{
+ SCM arg = SCM_EOL;
SCM res = SCM_EOL;
- SCM *lloc = &res, arg;
- if (SCM_IMP(args)) {
- SCM_VALIDATE_NULL (SCM_ARGn, args);
- return res;
- }
- SCM_VALIDATE_CONS (SCM_ARGn, args);
- while (1) {
- arg = SCM_CAR(args);
- args = SCM_CDR(args);
- if (SCM_IMP(args)) {
- *lloc = arg;
- SCM_VALIDATE_NULL (SCM_ARGn, args);
- return res;
- }
- SCM_VALIDATE_CONS (SCM_ARGn, args);
- for (; SCM_CONSP(arg); arg = SCM_CDR(arg)) {
- *lloc = scm_cons(SCM_CAR(arg), SCM_EOL);
- lloc = SCM_CDRLOC(*lloc);
+ SCM *lloc = &res;
+
+ while (SCM_NNULLP (args))
+ {
+ arg = SCM_CAR (args);
+ args = SCM_CDR (args);
+ if (SCM_NNULLP (args))
+ {
+ /* arg is not the last argument, thus it has to be copied */
+
+ SCM tortoise = arg;
+ SCM hare = arg;
+ while (SCM_CONSP (hare))
+ {
+ *lloc = scm_cons(SCM_CAR (hare), SCM_EOL);
+ lloc = SCM_CDRLOC (*lloc);
+ hare = SCM_CDR (hare);
+ if (SCM_CONSP (hare))
+ {
+ *lloc = scm_cons(SCM_CAR (hare), SCM_EOL);
+ lloc = SCM_CDRLOC (*lloc);
+ hare = SCM_CDR (hare);
+
+ tortoise = SCM_CDR (tortoise);
+ if (hare == tortoise)
+ {
+ SCM_MISC_ERROR ("Circular structure: ~S", SCM_LIST1 (arg));
+ }
+ }
+ }
+ SCM_VALIDATE_NULL (SCM_ARGn, hare);
+ }
}
- SCM_VALIDATE_NULL (SCM_ARGn, arg);
- }
+ *lloc = arg;
+ return res;
}
#undef FUNC_NAME
SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
(SCM args),
-"")
+ "A destructive version of @code{append} (@pxref{Pairs and Lists,,,r4rs,\n"
+ "The Revised^4 Report on Scheme}). The cdr field of each list's final\n"
+ "pair is changed to point to the head of the next list, so no consing is\n"
+ "performed. Return a pointer to the mutated list.")
#define FUNC_NAME s_scm_append_x
{
SCM arg;