summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-07-23 20:32:39 -0700
committerKaz Kylheku <kaz@kylheku.com>2024-07-23 20:32:39 -0700
commit96e0815b2838becd739d471c5e0edb7e3dac46fc (patch)
treee6acc6d2a9bb4e7766b26347327695b2fbe2a601
parent0ccb63709201223f00365b7ee99d3ef9aa5304d2 (diff)
downloadtxr-96e0815b2838becd739d471c5e0edb7e3dac46fc.tar.gz
txr-96e0815b2838becd739d471c5e0edb7e3dac46fc.tar.bz2
txr-96e0815b2838becd739d471c5e0edb7e3dac46fc.zip
make-like: use seq_build.
* lib.c (make_like): Simplify implementation using seq_build, which also lets it handle more cases. * tests/012/seq.tl: New tests. Some existing test fixed, including one for tuples*. * txr.1: Documentation updated: mainly that make-like doesn't strictly require a list argument.
-rw-r--r--lib.c59
-rw-r--r--tests/012/seq.tl8
-rw-r--r--txr.114
3 files changed, 31 insertions, 50 deletions
diff --git a/lib.c b/lib.c
index ed7f0b90..193f8196 100644
--- a/lib.c
+++ b/lib.c
@@ -2419,46 +2419,25 @@ val copy_list(val list)
val make_like(val list, val thatobj)
{
- if (list != thatobj) {
- switch (type(thatobj)) {
- case VEC:
- return vec_list(list);
- case STR:
- case LIT:
- case LSTR:
- if (!opt_compat || opt_compat > 101) {
- if (!list)
- return null_string;
- }
- if (is_chr(car(list)))
- return cat_str(list, nil);
- break;
- case BUF:
- if (!list)
- return make_buf(zero, zero, zero);
- if (integerp(car(list)))
- return buf_list(list);
- break;
- case COBJ:
- if (thatobj->co.cls == seq_iter_cls)
- {
- struct seq_iter *si = coerce(struct seq_iter *, thatobj->co.handle);
- return make_like(list, si->inf.obj);
- }
- if (obj_struct_p(thatobj)) {
- val from_list_meth = get_special_slot(thatobj, from_list_m);
- if (from_list_meth)
- return funcall1(from_list_meth, list);
- }
- if (thatobj->co.cls == carray_cls)
- return carray_list(list, carray_type(thatobj), nil);
- break;
- case NIL:
- case CONS:
- case LCONS:
- default:
- break;
- }
+ val self = lit("make-like");
+ type_t tli = type(list);
+ type_t tbj = type(thatobj);
+
+ if (tli != tbj &&
+ !(tli == NIL && tbj == CONS) &&
+ !(tli == CONS && tbj == NIL))
+ {
+ seq_iter_t it;
+ seq_build_t bu;
+ val elem;
+
+ seq_build_init(self, &bu, thatobj);
+ seq_iter_init(self, &it, list);
+
+ while (seq_get(&it, &elem))
+ seq_add(&bu, elem);
+
+ return seq_finish(&bu);
}
return list;
diff --git a/tests/012/seq.tl b/tests/012/seq.tl
index 97549500..29fea518 100644
--- a/tests/012/seq.tl
+++ b/tests/012/seq.tl
@@ -309,7 +309,7 @@
(tuples* 3 #() 1) (#(1 1 1)))
(test
- (lforce (tuples* 3 "a" 1)) :error)
+ (lforce (tuples* 3 "a" 1)) ((#\a 1 1)))
(mtest
(take 3 (tuples* 3 (range 0))) ((0 1 2) (1 2 3) (2 3 4))
@@ -1602,9 +1602,11 @@
(mtest
(make-like '(1 2 3) "") (1 2 3)
(make-like '(#\a #\b #\c) "") "abc"
- (make-like '(#\a #\b 3) "") :error
+ (make-like '(#\a #\b 3) "") (#\a #\b 3)
(make-like '(1 2 3) #()) #(1 2 3)
- (make-like '(1 2 3) #b'') #b'010203')
+ (make-like '(1 2 3) #b'') #b'010203'
+ (make-like #(1 2 3) nil) (1 2 3)
+ (make-like #(1 2 3) '(x)) (1 2 3))
(mtest
(seq-like "" 1 2 3) (1 2 3)
diff --git a/txr.1 b/txr.1
index a5fb51fa..a92a484a 100644
--- a/txr.1
+++ b/txr.1
@@ -34410,22 +34410,22 @@ of the language may specify additional iterable objects.
.coNP Functions @ make-like and @ seq-like
.synb
-.mets (make-like < list << object )
+.mets (make-like < seq << object )
.mets (seq-like < object << arg *)
.syne
.desc
The
.code make-like
function's
-.meta list
-argument must be a list. If
+.meta seq
+argument must be a sequence. If
.meta object
is a sequence type,
then
.meta list
is converted to the same type of sequence, if possible, and returned.
Otherwise the original
-.meta list
+.meta seq
is returned.
Conversion is supported to string and vector type, plus
@@ -34438,7 +34438,7 @@ is an object of a structure type which has a static function
then
.code make-like
calls that function, passing to it, and the resulting value is returned.
-.meta list
+.meta seq
and returns whatever value that function returns.
If
@@ -34484,10 +34484,10 @@ The result of
.code seq-like
is consistent with what the
.code make-like
-function would return if given a list of the
+function would return if given a sequence of the
.meta arg
values as the
-.meta list
+.meta seq
argument. That is to say, the following equivalence holds:
.verb