summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-02-27 07:03:17 -0800
committerKaz Kylheku <kaz@kylheku.com>2024-02-27 07:03:17 -0800
commit4177d2de918370b9cad5874952b42cb778aa00b8 (patch)
tree9ad098e702929129aa173b3228006faeedf484b3 /lib.c
parentabfc025c6e6c6db4acaeef74801dc4baaa2376bd (diff)
downloadtxr-4177d2de918370b9cad5874952b42cb778aa00b8.tar.gz
txr-4177d2de918370b9cad5874952b42cb778aa00b8.tar.bz2
txr-4177d2de918370b9cad5874952b42cb778aa00b8.zip
separate: rework using seq_build.
* lib.c (separate): switch statement with type-specific coding replaced with generic sequence iteration and building.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c88
1 files changed, 13 insertions, 75 deletions
diff --git a/lib.c b/lib.c
index 314fde4f..a612acff 100644
--- a/lib.c
+++ b/lib.c
@@ -3308,87 +3308,25 @@ val keep_keys_if(val pred, val seq, val keyfun_in)
return seq_finish(&bu);
}
-val separate(val pred, val seq_in, val keyfun_in)
+val separate(val pred, val seq, val keyfun_in)
{
val self = lit("separate");
val keyfun = default_null_arg(keyfun_in);
+ seq_iter_t it;
+ seq_build_t yea;
+ seq_build_t nay;
+ val elem;
- switch (type(seq_in)) {
- case NIL:
- return cons(nil, cons(nil, nil));
- case CONS:
- case LCONS:
- case COBJ:
- {
- list_collect_decl (yea, yptail);
- list_collect_decl (nay, nptail);
- val list = seq_in;
- val lastdiff = list;
- val was_yea = nil; /* Initialize to nil to silence compiler warning. */
-
- gc_hint(list);
-
- for (; list; list = cdr(list)) {
- val elem = car(list);
- val key = keyfun ? funcall1(keyfun, elem) : elem;
- val is_yea = if3(funcall1(pred, key), t, nil);
-
- if (list != seq_in && neq(is_yea, was_yea)) {
- if (was_yea)
- yptail = list_collect_nconc(yptail, ldiff(lastdiff, list));
- else
- nptail = list_collect_nconc(nptail, ldiff(lastdiff, list));
-
- lastdiff = list;
- }
-
- was_yea = is_yea;
- }
-
- if (was_yea)
- yptail = list_collect_nconc(yptail, lastdiff);
- else
- nptail = list_collect_nconc(nptail, lastdiff);
-
- return cons(yea, cons(nay, nil));
- }
- case LIT:
- case STR:
- case LSTR:
- {
- val yea = mkustring(zero);
- val nay = mkustring(zero);
- val str = seq_in;
- cnum len = c_fixnum(length_str(str), self), i;
-
- for (i = 0; i < len; i++) {
- val elem = chr_str(str, num_fast(i));
- val key = keyfun ? funcall1(keyfun, elem) : elem;
-
- string_extend(funcall1(pred, key) ? yea : nay, elem, tnil(i == len - 1));
- }
-
- return cons(yea, cons(nay, nil));
- }
- case VEC:
- {
- val yea = vector(zero, nil);
- val nay = vector(zero, nil);
- val vec = seq_in;
- cnum len = c_fixnum(length_vec(vec), self), i;
-
- for (i = 0; i < len; i++) {
- val elem = vecref(vec, num_fast(i));
- val key = keyfun ? funcall1(keyfun, elem) : elem;
-
- vec_push(funcall1(pred, key) ? yea : nay, elem);
- }
+ seq_iter_init(self, &it, seq);
+ seq_build_init(&yea, seq);
+ seq_build_init(&nay, seq);
- return cons(yea, cons(nay, nil));
- }
- default:
- uw_throwf(error_s, lit("~a: ~s isn't a sequence"), self, seq_in, nao);
+ while (seq_get(&it, &elem)) {
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
+ seq_add(funcall1(pred, key) ? &yea : &nay, elem);
}
+
+ return cons(seq_finish(&yea), cons(seq_finish(&nay), nil));
}
val separate_keys(val pred, val seq_in, val keyfun_in)