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
commit2cec86984b7110a6a464b992edb6160149a0a75f (patch)
tree1c585b943d8d1eebaa2b20182f5bc49afe796fae /lib.c
parent19a868e30bbae3ae01d176a8aca876a36f8dc571 (diff)
downloadtxr-2cec86984b7110a6a464b992edb6160149a0a75f.tar.gz
txr-2cec86984b7110a6a464b992edb6160149a0a75f.tar.bz2
txr-2cec86984b7110a6a464b992edb6160149a0a75f.zip
take: rewrite with seq_info; elide cons.
* lib.c (take_list_fun, take_while_list_fun): Renamed to lazy_take_list_fun and lazy_take_while_list_fun respectively. (lazy_take_list_fun, take): take upgraded to use seq_info to classify sequence. In the lazy list case, the state cons is elided; the list is passed as the function environment, and the remaining count is propagated in the lazy cons's car field. (lazy_take_while_list_fun, take_while): Similar changes. * txr.1: Fixed accidental reference to drop function in the documentation for the take function.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c62
1 files changed, 31 insertions, 31 deletions
diff --git a/lib.c b/lib.c
index cbf5c948..03f22587 100644
--- a/lib.c
+++ b/lib.c
@@ -9818,79 +9818,79 @@ val ends_with(val little, val big, val testfun, val keyfun)
return tnil(!mm || eql(pred(neg(mm)), length(little)));
}
-static val take_list_fun(val env, val lcons)
+static val lazy_take_list_fun(val list, val lcons)
{
- us_cons_bind (list, count, env);
+ val count = us_car(lcons);
us_rplaca(lcons, pop(&list));
- if3(le((count = pred(count)), zero) || list == nil,
- us_rplacd(lcons, nil),
- us_rplacd(lcons, make_lazy_cons(us_lcons_fun(lcons))));
+ if (list == nil || le((count = pred(count)), zero)) {
+ us_rplacd(lcons, nil);
+ } else {
+ val fun = us_lcons_fun(lcons);
+ us_rplacd(lcons, make_lazy_cons_car(fun, count));
+ us_func_set_env(fun, list);
+ }
- us_rplaca(env, list);
- us_rplacd(env, count);
return nil;
}
val take(val count, val seq)
{
- 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:
if (le(count, zero))
return nil;
- return make_lazy_cons(func_f1(cons(seq, count), take_list_fun));
- case LSTR:
- case LIT:
- case STR:
- case VEC:
+ return make_lazy_cons_car(func_f1(si.obj, lazy_take_list_fun), count);
+ case SEQ_VECLIKE:
return sub(seq, zero, count);
+ case SEQ_HASHLIKE:
+ type_mismatch(lit("take: hashes not supported"), nao);
default:
type_mismatch(lit("take: ~s is not a sequence"), seq, nao);
}
}
-static val take_while_list_fun(val env, val lcons)
+static val lazy_take_while_list_fun(val pred, val lcons)
{
- us_cons_bind (list, cell, env);
- us_cons_bind (pred, keyfun, cell);
+ us_cons_bind (keyfun, list, lcons);
us_rplaca(lcons, pop(&list));
if (!list || !funcall1(pred, funcall1(keyfun, car(list))))
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_while(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);
if (!funcall1(pred, funcall1(keyfun, (car(seq)))))
return nil;
- return make_lazy_cons(func_f1(cons(seq, cons(pred, keyfun)),
- take_while_list_fun));
- case LSTR:
- case LIT:
- case STR:
- case VEC:
+ return make_lazy_cons_car_cdr(func_f1(pred, lazy_take_while_list_fun),
+ keyfun, si.obj);
+ case SEQ_VECLIKE:
{
val pos = pos_if(notf(pred), seq, keyfun);
if (!pos)
return seq;
return sub(seq, zero, pos);
}
+ case SEQ_HASHLIKE:
+ type_mismatch(lit("take-while: hashes not supported"), nao);
default:
type_mismatch(lit("take-while: ~s is not a sequence"), seq, nao);
}