summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-02-21 03:08:11 -0800
committerKaz Kylheku <kaz@kylheku.com>2022-02-21 03:08:11 -0800
commitaad381bc6ce5458ef2483238066ae7fe1577d508 (patch)
treece47953b39b6a1fadcbf45052cc79c83f55bdbf6
parentc914063fd0eb8c02d8362b86a61933c656a938bc (diff)
downloadtxr-aad381bc6ce5458ef2483238066ae7fe1577d508.tar.gz
txr-aad381bc6ce5458ef2483238066ae7fe1577d508.tar.bz2
txr-aad381bc6ce5458ef2483238066ae7fe1577d508.zip
New functions: find-max-key and find-min-key.
* eval.c (eval_init): Register find-max-key and find-min-key intrinsics. * lib.c (find_max_key, find_min_key): New functions. * lib.h (find_max_key, find_min_key): Declared. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
-rw-r--r--eval.c2
-rw-r--r--lib.c30
-rw-r--r--lib.h2
-rw-r--r--stdlib/doc-syms.tl2
-rw-r--r--txr.140
5 files changed, 76 insertions, 0 deletions
diff --git a/eval.c b/eval.c
index bacee841..3d0db78c 100644
--- a/eval.c
+++ b/eval.c
@@ -7340,7 +7340,9 @@ void eval_init(void)
reg_fun(intern(lit("find-if"), user_package), func_n3o(find_if, 2));
reg_fun(intern(lit("rfind-if"), user_package), func_n3o(rfind_if, 2));
reg_fun(intern(lit("find-max"), user_package), func_n3o(find_max, 1));
+ reg_fun(intern(lit("find-max-key"), user_package), func_n3o(find_max_key, 1));
reg_fun(intern(lit("find-min"), user_package), func_n3o(find_min, 1));
+ reg_fun(intern(lit("find-min-key"), user_package), func_n3o(find_min_key, 1));
reg_fun(intern(lit("find-true"), user_package), func_n3o(find_true, 2));
reg_fun(intern(lit("multi-sort"), user_package), func_n3o(multi_sort, 2));
reg_fun(intern(lit("set-diff"), user_package), func_n4o(set_diff, 2));
diff --git a/lib.c b/lib.c
index 2a3b7680..ba8dca50 100644
--- a/lib.c
+++ b/lib.c
@@ -10940,11 +10940,41 @@ val find_max(val seq, val testfun, val keyfun)
}
}
+val find_max_key(val seq, val testfun_in, val keyfun_in)
+{
+ val self = lit("find-max-key");
+ val testfun = default_arg(testfun_in, greater_f);
+ val keyfun = default_arg(keyfun_in, identity_f);
+ seq_iter_t iter;
+ val elem;
+
+ seq_iter_init(self, &iter, seq);
+
+ if (seq_get(&iter, &elem)) {
+ val maxkey = funcall1(keyfun, elem);
+
+ while (seq_get(&iter, &elem)) {
+ val key = funcall1(keyfun, elem);
+ if (funcall2(testfun, key, maxkey))
+ maxkey = key;
+ }
+
+ return maxkey;
+ }
+
+ return nil;
+}
+
val find_min(val seq, val testfun, val keyfun)
{
return find_max(seq, default_arg(testfun, less_f), keyfun);
}
+val find_min_key(val seq, val testfun, val keyfun)
+{
+ return find_max_key(seq, default_arg(testfun, less_f), keyfun);
+}
+
val find_true(val pred, val seq, val key)
{
val self = lit("find-true");
diff --git a/lib.h b/lib.h
index d2d7a486..817e8d87 100644
--- a/lib.h
+++ b/lib.h
@@ -1197,7 +1197,9 @@ val rfind(val list, val key, val testfun, val keyfun);
val find_if(val pred, val list, val key);
val rfind_if(val pred, val list, val key);
val find_max(val seq, val testfun, val keyfun);
+val find_max_key(val seq, val testfun, val keyfun);
val find_min(val seq, val testfun, val keyfun);
+val find_min_key(val seq, val testfun, val keyfun);
val find_true(val pred, val list, val keyfun);
val posqual(val obj, val list);
val rposqual(val obj, val list);
diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl
index 8a472752..d2af2cc1 100644
--- a/stdlib/doc-syms.tl
+++ b/stdlib/doc-syms.tl
@@ -740,7 +740,9 @@
("find-frames" "N-02B97226")
("find-if" "N-00C9DFF6")
("find-max" "N-02BB4231")
+ ("find-max-key" "N-020038A0")
("find-min" "N-02BB4231")
+ ("find-min-key" "N-020038A0")
("find-package" "N-0250826D")
("find-struct-type" "N-01E5EEA7")
("find-symbol" "N-01EA8B50")
diff --git a/txr.1 b/txr.1
index 45ed6ecb..9ab36a25 100644
--- a/txr.1
+++ b/txr.1
@@ -35409,6 +35409,46 @@ the leftmost one is reported. See the notes under
.code pos-max
regarding duplicate maxima.
+.coNP Functions @ find-max-key and @ find-min-key
+.synb
+.mets (find-max-key < iterable [ testfun <> [ keyfun ]])
+.mets (find-min-key < iterable [ testfun <> [ keyfun ]])
+.syne
+.desc
+The
+.code find-min-key
+and
+.code find-max-key
+functions have the same argument conventions as, respectively,
+.code find-max
+and
+.code find-min
+and agree with those functions in regard to which element of the
+input sequence is identified: all these functions identify the
+element which maximizes or minimizes the value of
+.metn keyfun .
+
+Whereas
+.code find-max
+and
+.code find-min
+return the maximizing or minimizing element itself, the
+.code find-max-key
+and
+.code find-min-key
+functions return the value of
+.meta keyfun
+applied to the element.
+
+Under the default
+.meta keyfun
+value, that being the
+.code identity
+function, these functions behave the same as
+.code find-max
+and
+.codn find-min .
+
.coNP Functions @, uni @, isec @ diff and @ symdiff
.synb
.mets (uni < iter1 < iter1 >> [ testfun <> [ keyfun ]])