summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--eval.c6
-rw-r--r--lib.c51
-rw-r--r--lib.h1
-rw-r--r--txr.19
5 files changed, 69 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index c2547c5e..90619035 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2014-01-21 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (mapcarv, mappendv): Convert output to type of leftmost
+ input sequence.
+
+ * lib.c (make_like): New function.
+ (reverse, remq, remql, remqual, remove_if, keep_if, mapcar, mapcon,
+ mappend, set_diff): Convert output list to type of leftmost input
+ sequence.
+
+ * lib.h (make_like): Declared.
+
+ * txr.1: Documented.
+
+2014-01-21 Kaz Kylheku <kaz@kylheku.com>
+
* lib.c (car, cdr, ldiff): Extend to handle vectors and strings.
Thereby, numerous previously list-only operations in TXR Lisp
now magically handle strings and vectors.
diff --git a/eval.c b/eval.c
index e43bd2cc..8ac48da8 100644
--- a/eval.c
+++ b/eval.c
@@ -1828,6 +1828,7 @@ val mapcarv(val fun, val list_of_lists)
return mapcar(fun, car(list_of_lists));
} else {
val lofl = copy_list(list_of_lists);
+ val list_orig = car(list_of_lists);
list_collect_decl (out, otail);
for (;;) {
@@ -1837,7 +1838,7 @@ val mapcarv(val fun, val list_of_lists)
for (iter = lofl; iter; iter = cdr(iter)) {
val list = car(iter);
if (!list)
- return out;
+ return make_like(out, list_orig);
list_collect(atail, car(list));
*car_l(iter) = cdr(list);
}
@@ -1853,6 +1854,7 @@ static val mappendv(val fun, val list_of_lists)
return mappend(fun, car(list_of_lists));
} else {
val lofl = copy_list(list_of_lists);
+ val list_orig = car(list_of_lists);
list_collect_decl (out, otail);
for (;;) {
@@ -1862,7 +1864,7 @@ static val mappendv(val fun, val list_of_lists)
for (iter = lofl; iter; iter = cdr(iter)) {
val list = car(iter);
if (!list)
- return out;
+ return make_like(out, list_orig);
list_collect(atail, car(list));
*car_l(iter) = cdr(list);
}
diff --git a/lib.c b/lib.c
index 6e162c22..be9e030b 100644
--- a/lib.c
+++ b/lib.c
@@ -404,6 +404,27 @@ val copy_list(val list)
return out;
}
+val make_like(val list, val thatobj)
+{
+ if (list != thatobj) {
+ switch (type(thatobj)) {
+ case VEC:
+ return list_vector(list);
+ case STR:
+ case LIT:
+ case LSTR:
+ return cat_str(list, nil);
+ case NIL:
+ case CONS:
+ case LCONS:
+ default:
+ break;
+ }
+ }
+
+ return list;
+}
+
val nreverse(val in)
{
val rev = nil;
@@ -420,6 +441,7 @@ val nreverse(val in)
val reverse(val in)
{
+ val in_orig = in;
val rev = nil;
while (in) {
@@ -427,7 +449,7 @@ val reverse(val in)
in = cdr(in);
}
- return rev;
+ return make_like(rev, in_orig);
}
val append2(val list1, val list2)
@@ -673,6 +695,7 @@ val memqual(val obj, val list)
val remq(val obj, val list)
{
list_collect_decl (out, ptail);
+ val list_orig = list;
val lastmatch = cons(nil, list);
for (; list; list = cdr(list)) {
@@ -682,12 +705,13 @@ val remq(val obj, val list)
}
}
list_collect_nconc(ptail, cdr(lastmatch));
- return out;
+ return make_like(out, list_orig);
}
val remql(val obj, val list)
{
list_collect_decl (out, ptail);
+ val list_orig = list;
val lastmatch = cons(nil, list);
for (; list; list = cdr(list)) {
@@ -697,12 +721,13 @@ val remql(val obj, val list)
}
}
list_collect_nconc(ptail, cdr(lastmatch));
- return out;
+ return make_like(out, list_orig);
}
val remqual(val obj, val list)
{
list_collect_decl (out, ptail);
+ val list_orig = list;
val lastmatch = cons(nil, list);
for (; list; list = cdr(list)) {
@@ -712,12 +737,13 @@ val remqual(val obj, val list)
}
}
list_collect_nconc(ptail, cdr(lastmatch));
- return out;
+ return make_like(out, list_orig);
}
val remove_if(val pred, val list, val key)
{
list_collect_decl (out, ptail);
+ val list_orig = list;
val lastmatch = cons(nil, list);
if (!key)
@@ -733,12 +759,13 @@ val remove_if(val pred, val list, val key)
}
}
list_collect_nconc(ptail, cdr(lastmatch));
- return out;
+ return make_like(out, list_orig);
}
val keep_if(val pred, val list, val key)
{
list_collect_decl (out, ptail);
+ val list_orig = list;
val lastmatch = cons(nil, list);
if (!key)
@@ -754,7 +781,7 @@ val keep_if(val pred, val list, val key)
}
}
list_collect_nconc(ptail, cdr(lastmatch));
- return out;
+ return make_like(out, list_orig);
}
static val rem_lazy_rec(val obj, val list, val env, val func);
@@ -4320,31 +4347,34 @@ val copy_alist(val list)
val mapcar(val fun, val list)
{
list_collect_decl (out, iter);
+ val list_orig = list;
for (; list; list = cdr(list))
list_collect (iter, funcall1(fun, car(list)));
- return out;
+ return make_like(out, list_orig);
}
val mapcon(val fun, val list)
{
list_collect_decl (out, iter);
+ val list_orig = list;
for (; list; list = cdr(list))
list_collect_nconc (iter, funcall1(fun, list));
- return out;
+ return make_like(out, list_orig);
}
val mappend(val fun, val list)
{
list_collect_decl (out, iter);
+ val list_orig = list;
for (; list; list = cdr(list))
list_collect_append (iter, funcall1(fun, car(list)));
- return out;
+ return make_like(out, list_orig);
}
val merge(val list1, val list2, val lessfun, val keyfun)
@@ -4547,6 +4577,7 @@ val find_if(val pred, val list, val key)
val set_diff(val list1, val list2, val testfun, val keyfun)
{
list_collect_decl (out, ptail);
+ val list_orig = list1;
if (!keyfun)
keyfun = identity_f;
@@ -4568,7 +4599,7 @@ val set_diff(val list1, val list2, val testfun, val keyfun)
}
}
- return out;
+ return make_like(out, list_orig);
}
val length(val seq)
diff --git a/lib.h b/lib.h
index 80d1874c..301fe686 100644
--- a/lib.h
+++ b/lib.h
@@ -373,6 +373,7 @@ val *ltail(val *cons);
val pop(val *plist);
val push(val v, val *plist);
val copy_list(val list);
+val make_like(val list, val thatobj);
val nreverse(val in);
val reverse(val in);
val append2(val list1, val list2);
diff --git a/txr.1 b/txr.1
index 2e499bef..49333855 100644
--- a/txr.1
+++ b/txr.1
@@ -5037,6 +5037,15 @@ The ldiff operation starts with "abcd" and repeatedly applies cdr to produce
Operations based on car, cdr and ldiff, such as keep-if and remq extend to
strings and vectors.
+Derived list processing operations such as remq or mapcar obey the following
+rule: the returned object follows the type of the leftmost input list object.
+For instance, if one or more sequences are processed by mapcar, and the
+leftmost one is a character string, the function is expected to return
+characters, which are converted to a character string.
+
+The lazy versions of these functions such as mapcar* do not have this behavior;
+they produce lazy lists.
+
.SH CONTROL FLOW AND SEQUENCING
When the first element of a compound expression is an operator symbol,