summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-02-22 07:43:47 -0800
committerKaz Kylheku <kaz@kylheku.com>2022-02-22 07:43:47 -0800
commite987585d08122ecf3448a2d432346d2e128e5926 (patch)
tree582bcfcb1881c471578b598d62ad38429ade3d84 /lib.c
parentc38dbf7975d0df4758b295b90a47c1dbaaeaa976 (diff)
downloadtxr-e987585d08122ecf3448a2d432346d2e128e5926.tar.gz
txr-e987585d08122ecf3448a2d432346d2e128e5926.tar.bz2
txr-e987585d08122ecf3448a2d432346d2e128e5926.zip
find-max: convert to seq_info iteration.
* lib.c (find_max): Simplify into a single loop rather than handling various sequence types specially. This means it works for all iterable objects now. * txr.1: find-max documentation updated; discussion of hash tables removed, since the described behavior is the one expected for hash tables as iterables. * tests/012/seq.tl: Add some test coverage.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c81
1 files changed, 17 insertions, 64 deletions
diff --git a/lib.c b/lib.c
index ba8dca50..2d331a9f 100644
--- a/lib.c
+++ b/lib.c
@@ -10865,79 +10865,32 @@ val rfind(val item, val seq, val testfun_in, val keyfun_in)
}
}
-val find_max(val seq, val testfun, val keyfun)
+val find_max(val seq, val testfun_in, val keyfun_in)
{
val self = lit("find-max");
- seq_info_t si = seq_info(seq);
- testfun = default_arg(testfun, greater_f);
- keyfun = default_arg(keyfun, identity_f);
-
- switch (si.kind) {
- case SEQ_NIL:
- return nil;
- case SEQ_HASHLIKE:
- {
- struct hash_iter hi;
- val cell = (hash_iter_init(&hi, si.obj, self), hash_iter_next(&hi));
- val maxelt = cell;
- val maxkey = if2(cell, funcall1(keyfun, cell));
-
- while (cell && (cell = hash_iter_next(&hi))) {
- val key = funcall1(keyfun, cell);
- if (funcall2(testfun, key, maxkey)) {
- maxkey = key;
- maxelt = cell;
- }
- }
+ val testfun = default_arg(testfun_in, greater_f);
+ val keyfun = default_arg(keyfun_in, identity_f);
+ seq_iter_t iter;
+ val elem;
- return maxelt;
- }
- case SEQ_LISTLIKE:
- {
- val maxelt = car(z(si.obj));
- val maxkey = funcall1(keyfun, maxelt);
+ seq_iter_init(self, &iter, seq);
- gc_hint(seq);
+ if (seq_get(&iter, &elem)) {
+ val maxkey = funcall1(keyfun, elem);
+ val maxelem = elem;
- 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;
- }
+ while (seq_get(&iter, &elem)) {
+ val key = funcall1(keyfun, elem);
+ if (funcall2(testfun, key, maxkey)) {
+ maxkey = key;
+ maxelem = elem;
}
-
- return maxelt;
}
- case SEQ_VECLIKE:
- {
- val vec = si.obj;
- cnum len = c_fixnum(length(vec), self);
- if (len > 0) {
- val maxelt = ref(vec, zero);
- val maxkey = funcall1(keyfun, maxelt);
- cnum i;
-
- for (i = 1; i < len; i++) {
- val elt = ref(vec, num_fast(i));
- val key = funcall1(keyfun, elt);
- if (funcall2(testfun, key, maxkey)) {
- maxkey = key;
- maxelt = elt;
- }
- }
-
- return maxelt;
- }
-
- return nil;
- }
- case SEQ_NOTSEQ:
- default:
- unsup_obj(self, seq);
+ return maxelem;
}
+
+ return nil;
}
val find_max_key(val seq, val testfun_in, val keyfun_in)