summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-10-12 21:10:40 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-10-12 21:10:40 -0700
commit1c11fe21f49559fbb0f2ee8fa9b702338207e7a0 (patch)
treed50ac6976f167da9d3b0bd3150ee81522b332209 /lib.c
parent03699dd7d47cbf95552bed02e5c37f078528a3b2 (diff)
downloadtxr-1c11fe21f49559fbb0f2ee8fa9b702338207e7a0.tar.gz
txr-1c11fe21f49559fbb0f2ee8fa9b702338207e7a0.tar.bz2
txr-1c11fe21f49559fbb0f2ee8fa9b702338207e7a0.zip
find-max and find-min support hashes.
* lib.c (find_max): Restructured to implement separately for vectors and lists. Support hash tables. * txr.1: Document find-min and find-max for hashes.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/lib.c b/lib.c
index 834d137f..702b3946 100644
--- a/lib.c
+++ b/lib.c
@@ -7544,8 +7544,6 @@ val rfind(val item, val list, val testfun, val keyfun)
val find_max(val seq, val testfun, val keyfun)
{
- val maxkey;
- val maxelt;
seq = nullify(seq);
@@ -7555,21 +7553,65 @@ val find_max(val seq, val testfun, val keyfun)
testfun = default_arg(testfun, greater_f);
keyfun = default_arg(keyfun, identity_f);
- maxelt = car(seq);
- maxkey = funcall1(keyfun, maxelt);
+ switch (type(seq)) {
+ case COBJ:
+ if (seq->co.cls == hash_s) {
+ val hiter = hash_begin(seq);
+ val cell = hash_next(hiter);
+ val maxelt = cell;
+ val maxkey = if2(cell, funcall1(keyfun, cell));
+
+ while (cell && (cell = hash_next(hiter))) {
+ val key = funcall1(keyfun, cell);
+ if (funcall2(testfun, key, maxkey)) {
+ maxkey = key;
+ maxelt = cell;
+ }
+ }
- gc_hint(seq);
+ return maxelt;
+ }
+ /* fallthrough */
+ case CONS:
+ case LCONS:
+ {
+ val maxelt = car(seq);
+ val maxkey = funcall1(keyfun, maxelt);
- for (seq = cdr(seq); seq; seq = cdr(seq)) {
- val elt = car(seq);
- val key = funcall1(keyfun, elt);
- if (funcall2(testfun, key, maxkey)) {
- maxkey = key;
- maxelt = elt;
+ gc_hint(seq);
+
+ for (seq = cdr(seq); seq; seq = cdr(seq)) {
+ val elt = car(seq);
+ val key = funcall1(keyfun, elt);
+ if (funcall2(testfun, key, maxkey)) {
+ maxkey = key;
+ maxelt = elt;
+ }
+ }
+ return maxelt;
}
- }
+ case STR:
+ case LSTR:
+ case VEC:
+ {
+ val maxelt = ref(seq, zero);
+ val maxkey = funcall1(keyfun, maxelt);
+ val len = length(seq);
+ val i;
- return maxelt;
+ for (i = zero; lt(i, len); i = succ(i)) {
+ val elt = ref(seq, i);
+ val key = funcall1(keyfun, elt);
+ if (funcall2(testfun, key, maxkey)) {
+ maxkey = key;
+ maxelt = elt;
+ }
+ }
+ return maxelt;
+ }
+ default:
+ uw_throwf(error_s, lit("find-max: unsupporte object ~s is a literal"), seq, nao);
+ }
}
val find_min(val seq, val testfun, val keyfun)