diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-11-11 06:33:01 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-11-11 06:33:01 -0800 |
commit | 82020af157ad104be3a62b57053d2420d17785f9 (patch) | |
tree | e2a54d56d981a7d6e2c657e154fa264b237546b4 | |
parent | 73368784f2c3d69a0fbc227420550b4b1e05d4ea (diff) | |
download | txr-82020af157ad104be3a62b57053d2420d17785f9.tar.gz txr-82020af157ad104be3a62b57053d2420d17785f9.tar.bz2 txr-82020af157ad104be3a62b57053d2420d17785f9.zip |
Improve reverse and nreverse.
* lib.c (nreverse): Handle strings and vectors
individually, and do strings and vectors in-place.
(reverse): Handle strings and vectors individually,
by duplicating and then in place. Handle lazy
strings by forcing, then reversing a copy.
-rw-r--r-- | lib.c | 84 |
1 files changed, 68 insertions, 16 deletions
@@ -793,31 +793,83 @@ loc list_collect_append(loc ptail, val obj) val nreverse(val in) { - val rev = nil; + switch (type(in)) { + case NIL: + return nil; + case CONS: + case LCONS: + { + val rev = nil; - while (in) { - val temp = cdr(in); - set(cdr_l(in), rev); - rev = in; - in = temp; - } + while (in) { + val temp = cdr(in); + set(cdr_l(in), rev); + rev = in; + in = temp; + } - return rev; + return rev; + } + case VEC: + case STR: + { + cnum len = c_num(length(in)); + cnum i; + + for (i = 0; i < len / 2; i++) { + cnum j = len - i - 1; + val tmp = ref(in, num_fast(i)); + refset(in, num_fast(i), ref(in, num_fast(j))); + refset(in, num_fast(j), tmp); + } + + return in; + } + default: + uw_throwf(error_s, lit("nreverse: cannot reverse ~s"), in, nao); + } } val reverse(val in) { - val in_orig = in; - val rev = nil; + switch (type(in)) { + case NIL: + return nil; + case CONS: + case LCONS: + { + val rev = nil; - in = nullify(in); + while (in) { + rev = cons(car(in), rev); + in = cdr(in); + } - while (in) { - rev = cons(car(in), rev); - in = cdr(in); - } + return rev; + } + case LSTR: + in = lazy_str_force(in); + /* fallthrough */ + case VEC: + case STR: + case LIT: + { + val obj = copy(in); + cnum len = c_num(length(in)); + cnum i; - return make_like(rev, in_orig); + for (i = 0; i < len / 2; i++) { + cnum j = len - i - 1; + val tmp = ref(obj, num_fast(i)); + refset(obj, num_fast(i), ref(obj, num_fast(j))); + refset(obj, num_fast(j), tmp); + } + + return obj; + } + default: + uw_throwf(error_s, lit("reverse: cannot reverse ~s"), in, nao); + } } val append2(val list1, val list2) |