summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-02-05 07:46:48 -0800
committerKaz Kylheku <kaz@kylheku.com>2017-02-05 07:46:48 -0800
commitb1a8da709c6fc23122cd0f1c1999688ceff27a38 (patch)
tree994d78354ddd42da0bc0614eb6c18e7af3044283 /lib.c
parentb15b71016f255e91e6663a22ab61719330246c87 (diff)
downloadtxr-b1a8da709c6fc23122cd0f1c1999688ceff27a38.tar.gz
txr-b1a8da709c6fc23122cd0f1c1999688ceff27a38.tar.bz2
txr-b1a8da709c6fc23122cd0f1c1999688ceff27a38.zip
keep/remove: reduce duplication, optimize.
* lib.c (rem_impl): New static function. (remove_if): Rewritten similarly to rem_impl. (remq, remql, remqual, keepq, keepql, keepqual): Reduced to wrappers around rem_impl. (keep_if): Wrapper around remove_if with test negated. * lib.c (remq, remql, remqual, remove_if, keepq, keepql, keepqual, keep_if): Argument names adjusted.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c258
1 files changed, 128 insertions, 130 deletions
diff --git a/lib.c b/lib.c
index 11f9b520..92c7c027 100644
--- a/lib.c
+++ b/lib.c
@@ -1519,179 +1519,177 @@ val rmember_if(val pred, val list, val key)
return found;
}
-val remq(val obj, val list_orig, val keyfun)
+static val rem_impl(val (*eqfun)(val, val),
+ val obj, val seq_in, val keyfun_in)
{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
+ val keyfun = default_bool_arg(keyfun_in);
- keyfun = default_bool_arg(keyfun);
+ switch (type(seq_in)) {
+ case NIL:
+ return nil;
+ case CONS:
+ case LCONS:
+ case COBJ:
+ {
+ list_collect_decl (out, ptail);
+ val list = seq_in;
+ val lastmatch = cons(nil, list);
- gc_hint(list);
+ gc_hint(list);
- for (; list; list = cdr(list)) {
- val elem = car(list);
- val key = keyfun ? funcall1(keyfun, elem) : elem;
+ for (; list; list = cdr(list)) {
+ val elem = car(list);
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
- if (key == obj) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
+ if (eqfun(key, obj)) {
+ ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
+ lastmatch = list;
+ }
+ }
+ ptail = list_collect_nconc(ptail, cdr(lastmatch));
+ return out;
}
- }
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
-}
-
-val remql(val obj, val list_orig, val keyfun)
-{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
-
- keyfun = default_bool_arg(keyfun);
+ case LIT:
+ case STR:
+ case LSTR:
+ {
+ val out = mkustring(zero);
+ val str = seq_in;
+ cnum len = c_num(length_str(str)), i;
- gc_hint(list);
+ for (i = 0; i < len; i++) {
+ val elem = chr_str(str, num_fast(i));
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
- for (; list; list = cdr(list)) {
- val elem = car(list);
- val key = keyfun ? funcall1(keyfun, elem) : elem;
+ if (!eqfun(key, obj))
+ string_extend(out, elem);
+ }
- if (eql(key, obj)) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
+ return out;
}
- }
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
-}
-
-val remqual(val obj, val list_orig, val keyfun)
-{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
-
- keyfun = default_bool_arg(keyfun);
+ case VEC:
+ {
+ val out = vector(zero, nil);
+ val vec = seq_in;
+ cnum len = c_num(length_vec(vec)), i;
- gc_hint(list);
+ for (i = 0; i < len; i++) {
+ val elem = vecref(vec, num_fast(i));
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
- for (; list; list = cdr(list)) {
- val elem = car(list);
- val key = keyfun ? funcall1(keyfun, elem) : elem;
+ if (!eqfun(key, obj))
+ vec_push(out, elem);
+ }
- if (equal(key, obj)) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
+ return out;
}
+ default:
+ uw_throwf(error_s, lit("remq: ~s isn't a sequence"), in, nao);
}
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
}
-val remove_if(val pred, val list_orig, val key)
+val remove_if(val pred, val seq_in, val keyfun_in)
{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
+ val keyfun = default_bool_arg(keyfun_in);
- key = default_arg(key, identity_f);
+ switch (type(seq_in)) {
+ case NIL:
+ return nil;
+ case CONS:
+ case LCONS:
+ case COBJ:
+ {
+ list_collect_decl (out, ptail);
+ val list = seq_in;
+ val lastmatch = cons(nil, list);
- gc_hint(list);
+ gc_hint(list);
- for (; list; list = cdr(list)) {
- val subj = funcall1(key, car(list));
- val satisfies = funcall1(pred, subj);
+ for (; list; list = cdr(list)) {
+ val elem = car(list);
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
- if (satisfies) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
+ if (funcall1(pred, key)) {
+ ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
+ lastmatch = list;
+ }
+ }
+ ptail = list_collect_nconc(ptail, cdr(lastmatch));
+ return out;
}
- }
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
-}
-
-val keepq(val obj, val list_orig, val key)
-{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
+ case LIT:
+ case STR:
+ case LSTR:
+ {
+ val out = mkustring(zero);
+ val str = seq_in;
+ cnum len = c_num(length_str(str)), i;
- key = default_arg(key, identity_f);
+ for (i = 0; i < len; i++) {
+ val elem = chr_str(str, num_fast(i));
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
- gc_hint(list);
+ if (!funcall1(pred, key))
+ string_extend(out, elem);
+ }
- for (; list; list = cdr(list)) {
- if (funcall1(key, car(list)) != obj) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
+ return out;
}
- }
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
-}
-
-val keepql(val obj, val list_orig, val key)
-{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
+ case VEC:
+ {
+ val out = vector(zero, nil);
+ val vec = seq_in;
+ cnum len = c_num(length_vec(vec)), i;
- key = default_arg(key, identity_f);
+ for (i = 0; i < len; i++) {
+ val elem = vecref(vec, num_fast(i));
+ val key = keyfun ? funcall1(keyfun, elem) : elem;
- gc_hint(list);
+ if (!funcall1(pred, key))
+ vec_push(out, elem);
+ }
- for (; list; list = cdr(list)) {
- if (!eql(funcall1(key, car(list)), obj)) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
+ return out;
}
+ default:
+ uw_throwf(error_s, lit("remq: ~s isn't a sequence"), in, nao);
}
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
}
-val keepqual(val obj, val list_orig, val key)
-{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
-
- key = default_arg(key, identity_f);
- gc_hint(list);
+val remq(val obj, val seq, val keyfun)
+{
+ return rem_impl(eq, obj, seq, keyfun);
+}
- for (; list; list = cdr(list)) {
- if (!equal(funcall1(key, car(list)), obj)) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
- }
- }
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
+val remql(val obj, val seq, val keyfun)
+{
+ return rem_impl(eql, obj, seq, keyfun);
}
-val keep_if(val pred, val list_orig, val key)
+val remqual(val obj, val seq, val keyfun)
{
- list_collect_decl (out, ptail);
- val list = tolist(list_orig);
- val lastmatch = cons(nil, list);
+ return rem_impl(equal, obj, seq, keyfun);
+}
- key = default_arg(key, identity_f);
+val keepq(val obj, val seq, val keyfun)
+{
+ return rem_impl(neq, obj, seq, keyfun);
+}
- gc_hint(list);
+val keepql(val obj, val seq, val keyfun)
+{
+ return rem_impl(neql, obj, seq, keyfun);
+}
- for (; list; list = cdr(list)) {
- val subj = funcall1(key, car(list));
- val satisfies = funcall1(pred, subj);
+val keepqual(val obj, val seq, val keyfun)
+{
+ return rem_impl(nequal, obj, seq, keyfun);
+}
- if (!satisfies) {
- ptail = list_collect_nconc(ptail, ldiff(cdr(lastmatch), list));
- lastmatch = list;
- }
- }
- ptail = list_collect_nconc(ptail, cdr(lastmatch));
- return make_like(out, list_orig);
+val keep_if(val pred, val seq, val keyfun)
+{
+ return remove_if(notf(pred), seq, keyfun);
}
static val rem_lazy_rec(val obj, val list, val env, val func);