summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--lib.c40
-rw-r--r--txr.139
3 files changed, 65 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 67295649..c7c3cba3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2014-06-27 Kaz Kylheku <kaz@kylheku.com>
+ * lib.c (where, sel): Extend into hashes.
+
+ * txr.1: document hash support for select and where.
+
+2014-06-27 Kaz Kylheku <kaz@kylheku.com>
+
Bugfix: apply_intrinsic and iapply must not destructively
manipulate argument lists.
diff --git a/lib.c b/lib.c
index e84b098f..8a6f9ed2 100644
--- a/lib.c
+++ b/lib.c
@@ -5537,13 +5537,23 @@ val search(val seq, val key, val testfun, val keyfun)
val where(val seq_in, val func)
{
list_collect_decl (out, ptail);
- val seq = nullify(seq_in);
- val idx = zero;
- for (; seq; seq = cdr(seq), idx = plus(idx, one)) {
- val elt = car(seq);
- if (funcall1(func, elt))
- ptail = list_collect(ptail, idx);
+ if (hashp(seq_in)) {
+ val hiter = hash_begin(seq_in);
+ val cell;
+
+ while ((cell = hash_next(hiter)))
+ if (funcall1(func, cdr(cell)))
+ ptail = list_collect(ptail, car(cell));
+ } else {
+ val seq = nullify(seq_in);
+ val idx = zero;
+
+ for (; seq; seq = cdr(seq), idx = plus(idx, one)) {
+ val elt = car(seq);
+ if (funcall1(func, elt))
+ ptail = list_collect(ptail, idx);
+ }
}
return out;
@@ -5576,6 +5586,24 @@ val sel(val seq_in, val where_in)
}
}
break;
+ case COBJ:
+ if (!hashp(seq))
+ type_mismatch(lit("select: ~s is not a sequence or hash"), seq, nao);
+ {
+ val newhash = make_similar_hash(seq);
+
+ for (; where; where = cdr(where)) {
+ val found;
+ loc pfound = mkcloc(found);
+ val key = car(where);
+ val value = gethash_f(seq, car(where), pfound);
+
+ if (found)
+ sethash(newhash, key, value);
+ }
+
+ return newhash;
+ }
default:
{
val len = length(seq);
diff --git a/txr.1 b/txr.1
index 6cc8a056..f2f26476 100644
--- a/txr.1
+++ b/txr.1
@@ -7836,17 +7836,20 @@ the resulting value is used in its place.
.TP
Syntax:
- (where <sequence> <function>)
+ (where <object> <function>)
.TP
Description:
-The where function searches <sequence> for elements which satisfy <function>,
-and returns a list of the numeric indices of those elements within
-<sequence>, in order of increasing index.
+If <object> is a sequence, the where function returns
+a list of the numeric indices of those of its elements which satisfy
+<function>. The numeric indices appear in increasing order.
+
+If <object> is a hash, the where function returns an unordered list
+of keys which have values which satisfy <function>.
<function> must be a function that can be called with one argument.
-For each element of <sequence>, <function> is called with that element
+For each element of <object>, <function> is called with that element
as an argument. If a non-nil value is returned, then the zero-based index of
that element is added to a list. Finally, the list is returned.
@@ -7855,22 +7858,30 @@ that element is added to a list. Finally, the list is returned.
.TP
Syntax:
- (select <sequence> <index-list>)
+ (select <object> <index-list>)
.TP
Description:
-The select function returns a sequence, of the same kind as <sequence>,
-which consists of those elements of sequence which are identified by
-the numeric indices in <index-list>.
+The select function returns an object, of the same kind as <object>,
+which consists of those elements of <object> which are identified by
+the indices in <index-list>.
-The select function stops processing <sequence> upon encountering
-an index inside <index-list> which is out of range.
+If <object> is a sequence, then <index-list> consists of numeric
+indices. The select function stops processing <object> upon encountering an
+index inside <index-list> which is out of range. (Rationale: without
+this strict behavior, select would not be able to terminate if
+<index-list> is infinite.)
-If <sequence> is a list, then <index-list> must contain montonically increasing
-numeric values, even if no value is out of range, since the <select> function
+If <object> is a list, then <index-list> must contain montonically increasing
+numeric values, even if no value is out of range, since the select function
makes a single pass through the list based on the assumption that indices
-are ordered.
+are ordered. (Rationale: optmization.)
+
+If <object> is a hash, then <index-list> is a list of keys. A new hash is
+returned which contains those elements of <object> whose keys appear
+in <index-list>. All of <index-list> is processed, even if it contains
+keys which are not in <object>.
.SS Function tree-find