diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-10-13 06:44:38 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-10-13 06:44:38 -0700 |
commit | 98466491da86fa8d1c5071beaefcd35c057a8e60 (patch) | |
tree | 86e129303b173b6b4e3a6560f2315ce373dba04b | |
parent | f5ba54f7d2fc44fd39a4f44fab32e20c7d91be2c (diff) | |
download | txr-98466491da86fa8d1c5071beaefcd35c057a8e60.tar.gz txr-98466491da86fa8d1c5071beaefcd35c057a8e60.tar.bz2 txr-98466491da86fa8d1c5071beaefcd35c057a8e60.zip |
Overhaul where funtion.
* lib.c (where): Implement faster ref-based access for vectors
and strings. Support abstract sequence structs.
-rw-r--r-- | lib.c | 57 |
1 files changed, 43 insertions, 14 deletions
@@ -8544,25 +8544,54 @@ val where(val func, val seq) seq = f; } - if (hashp(seq)) { - val hiter = hash_begin(seq); - val cell; + seq = nullify(seq); - while ((cell = hash_next(hiter))) - if (funcall1(func, cdr(cell))) - ptail = list_collect(ptail, car(cell)); - } else { - val idx = zero; + switch (type(seq)) { + case COBJ: + if (seq->co.cls == hash_s) { + val hiter = hash_begin(seq); + val cell; - seq = nullify(seq); + while ((cell = hash_next(hiter))) + if (funcall1(func, cdr(cell))) + ptail = list_collect(ptail, car(cell)); + break; + } + /* fallthrough */ + case NIL: + case CONS: + case LCONS: + { + val idx = zero; - gc_hint(seq); + gc_hint(seq); - for (; seq; seq = cdr(seq), idx = plus(idx, one)) { - val elt = car(seq); - if (funcall1(func, elt)) - ptail = list_collect(ptail, idx); + for (; seq; seq = cdr(seq), idx = plus(idx, one)) { + val elt = car(seq); + if (funcall1(func, elt)) + ptail = list_collect(ptail, idx); + } } + break; + case LIT: + case STR: + case LSTR: + case VEC: + { + val idx; + val len = length(seq); + + gc_hint(seq); + + for (idx = zero; lt(idx, len); idx = plus(idx, one)) { + val elt = ref(seq, idx); + if (funcall1(func, elt)) + ptail = list_collect(ptail, idx); + } + } + break; + default: + type_mismatch(lit("where: ~s is not a sequence"), seq, nao); } return out; |