summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-03-20 06:19:28 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-03-20 06:19:28 -0700
commit004e19fb9ad4ffdec3cd2389289580c112b715c1 (patch)
tree7d0877a6a0a083fcf095af0bcf9a92dc1a7f5803 /lib.c
parent2cec86984b7110a6a464b992edb6160149a0a75f (diff)
downloadtxr-004e19fb9ad4ffdec3cd2389289580c112b715c1.tar.gz
txr-004e19fb9ad4ffdec3cd2389289580c112b715c1.tar.bz2
txr-004e19fb9ad4ffdec3cd2389289580c112b715c1.zip
take-until: rewrite with seq_info; elide cons.
* lib.c (take_until_list_fun): Renamed to lazy_take_until_list_fun. (lazy_take_until_list_fun, take_until): take_until upgraded to use seq_info to classify sequence. In the lazy list case, the state cons is elided; the predicate function is passed as the function environment, and the key function and list being traversed are propagated via the lazy cons car and cdr.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c29
1 files changed, 13 insertions, 16 deletions
diff --git a/lib.c b/lib.c
index 03f22587..0524a5d9 100644
--- a/lib.c
+++ b/lib.c
@@ -9896,43 +9896,40 @@ val take_while(val pred, val seq, val keyfun)
}
}
-static val take_until_list_fun(val env, val lcons)
+static val lazy_take_until_list_fun(val pred, val lcons)
{
- us_cons_bind (list, cell, env);
- us_cons_bind (pred, keyfun, cell);
+ us_cons_bind (keyfun, list, lcons);
val item = pop(&list);
-
us_rplaca(lcons, item);
if (!list || funcall1(pred, funcall1(keyfun, item)))
us_rplacd(lcons, nil);
else
- us_rplacd(lcons, make_lazy_cons(us_lcons_fun(lcons)));
+ us_rplacd(lcons, make_lazy_cons_car_cdr(us_lcons_fun(lcons), keyfun, list));
- us_rplaca(env, list);
return nil;
}
val take_until(val pred, val seq, val keyfun)
{
- switch (type(seq)) {
- case NIL:
+ seq_info_t si = seq_info(seq);
+
+ switch (si.kind) {
+ case SEQ_NIL:
return nil;
- case CONS:
- case LCONS:
+ case SEQ_LISTLIKE:
keyfun = default_arg(keyfun, identity_f);
- return make_lazy_cons(func_f1(cons(seq, cons(pred, keyfun)),
- take_until_list_fun));
- case LSTR:
- case LIT:
- case STR:
- case VEC:
+ return make_lazy_cons_car_cdr(func_f1(pred, lazy_take_until_list_fun),
+ keyfun, si.obj);
+ case SEQ_VECLIKE:
{
val pos = pos_if(pred, seq, keyfun);
if (!pos)
return seq;
return sub(seq, zero, succ(pos));
}
+ case SEQ_HASHLIKE:
+ type_mismatch(lit("take-until: hashes not supported"), nao);
default:
type_mismatch(lit("take-until: ~s is not a sequence"), seq, nao);
}