summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-06-14 07:21:56 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-06-14 07:21:56 -0700
commitdc0f9b2d38c58f7058d44e07ae04fde94356473b (patch)
treea22f7696eebfb7a94552792c334f729064ac0036
parentfdbd49a83ce4a567824c2830e202735d59b55a84 (diff)
downloadtxr-dc0f9b2d38c58f7058d44e07ae04fde94356473b.tar.gz
txr-dc0f9b2d38c58f7058d44e07ae04fde94356473b.tar.bz2
txr-dc0f9b2d38c58f7058d44e07ae04fde94356473b.zip
select: maintenance.
* lib.c (sel): Function converted to seq_info and iterators. Negative indices handled in list case. Self-name corrected to select; the C function is called sel just to avoid clashing with POSIX select. * txr.1: Documentation updated.
-rw-r--r--lib.c72
-rw-r--r--txr.125
2 files changed, 56 insertions, 41 deletions
diff --git a/lib.c b/lib.c
index 01e18b03..e3f63386 100644
--- a/lib.c
+++ b/lib.c
@@ -10479,66 +10479,72 @@ val where(val func, val seq)
}
}
-val sel(val seq_in, val where_in)
+val sel(val seq, val where_in)
{
- val self = lit("sel");
+ val self = lit("select");
list_collect_decl (out, ptail);
- val seq = nullify(seq_in);
val where = if3(functionp(where_in),
funcall1(where_in, seq),
- nullify(where_in));
+ where_in);
+ seq_info_t si = seq_info(seq);
+ seq_iter_t wh_iter;
+ val wh;
- switch (type(seq)) {
- case NIL:
+ seq_iter_init(self, &wh_iter, where);
+
+ switch (si.kind) {
+ case SEQ_NIL:
return nil;
- case COBJ:
- if (hashp(seq))
+ case SEQ_HASHLIKE:
{
- val newhash = make_similar_hash(seq);
-
- for (; where; where = cdr(where)) {
- val key = car(where);
- val found = gethash_e(self, seq, key);
+ val newhash = make_similar_hash(si.obj);
+ while (seq_get(&wh_iter, &wh)) {
+ val found = gethash_e(self, seq, wh);
if (found)
- sethash(newhash, key, cdr(found));
+ sethash(newhash, wh, cdr(found));
}
return newhash;
}
- if (seq->co.cls == carray_s)
- goto carray;
- /* fallthrough */
- case CONS:
- case LCONS:
+ case SEQ_LISTLIKE:
{
val idx = zero;
+ val iter = si.obj;
+ val len = nil;
+
+ while (iter && seq_peek(&wh_iter, &wh)) {
+ if (minusp(wh))
+ wh = plus(wh, len ? len : (len = length(seq)));
+ if (lt(wh, idx)) {
+ seq_geti(&wh_iter);
+ continue;
+ } else if (eql(wh, idx)) {
+ ptail = list_collect(ptail, car(iter));
+ seq_geti(&wh_iter);
+ }
- for (; seq && where; seq = cdr(seq), idx = plus(idx, one)) {
- val wh = nil;
-
- for (; where && lt(wh = car(where), idx); where = cdr(where))
- ; /* empty */
-
- if (eql(wh, idx))
- ptail = list_collect (ptail, car(seq));
+ iter = cdr(iter);
+ idx = plus(idx, one);
}
}
break;
- carray:
- default:
+ case SEQ_VECLIKE:
{
val len = length(seq);
- for (; where; where = cdr(where)) {
- val wh = car(where);
+
+ while (seq_get(&wh_iter, &wh)) {
if (ge(wh, len))
break;
- ptail = list_collect (ptail, ref(seq, car(where)));
+ ptail = list_collect(ptail, ref(si.obj, wh));
}
}
break;
+ case SEQ_NOTSEQ:
+ type_mismatch(lit("~a: ~s is not a sequence"), self, seq, nao);
}
- return make_like(out, seq_in);
+
+ return make_like(out, seq);
}
static val do_relate(val env, val arg)
diff --git a/txr.1 b/txr.1
index 7e85020f..ad3b2ee7 100644
--- a/txr.1
+++ b/txr.1
@@ -28469,14 +28469,16 @@ If
is a sequence, then
.meta index-list
consists of numeric
-indices. The
-.code select
-function stops processing
-.meta object
-upon encountering an
-index inside
+indices. The length of the sequence, as reported by the
+.code length
+function, is added to every
.meta index-list
-which is out of range. (Rationale: without
+value which is negative.
+The
+.code select
+function stops collecting values upon encountering an index value which is
+greater than or equal to the length of the sequence.
+(Rationale: without
this strict behavior,
.code select
would not be able to terminate if
@@ -28485,7 +28487,7 @@ is infinite.)
If
.meta object
-is a list, then
+is, more specifically, a list-like sequence, then
.meta index-list
must contain monotonically increasing
numeric values, even if no value is out of range, since the
@@ -28493,6 +28495,12 @@ numeric values, even if no value is out of range, since the
function
makes a single pass through the list based on the assumption that indices
are ordered. (Rationale: optimization.)
+This requirement for monotonicity applies to the values which
+result after negative indices are displaced by the sequence length
+Also, in this list-like sequence case, values taken from
+.meta index-list
+which are still negative after being displaced by the sequence length are
+ignored.
If
.meta object
@@ -28509,6 +28517,7 @@ All of
is processed, even if it contains
keys which are not in
.metn object .
+The nonexistent keys are ignored.
The
.code select