summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-01-20 01:03:51 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-01-20 01:03:51 -0800
commit9a2f9df335393284f6af2d95dbd65cb606792ad8 (patch)
tree3b5879d84420fd384eb788c576658c3dd5a4ef71
parent54d0988406a70c7849a10d9ada1dbdff761adf8f (diff)
downloadtxr-9a2f9df335393284f6af2d95dbd65cb606792ad8.tar.gz
txr-9a2f9df335393284f6af2d95dbd65cb606792ad8.tar.bz2
txr-9a2f9df335393284f6af2d95dbd65cb606792ad8.zip
New function: hash-keys-of.
* hash.c (hash_keys_of): New function. (hash_init): Register hash-keys-of intrinsic * hash.h (hash_keys_of): Declared. * txr.1: Documented.
-rw-r--r--hash.c21
-rw-r--r--hash.h1
-rw-r--r--txr.111
3 files changed, 32 insertions, 1 deletions
diff --git a/hash.c b/hash.c
index a6772c29..8040fa68 100644
--- a/hash.c
+++ b/hash.c
@@ -1808,6 +1808,26 @@ val hash_revget(val hash, val value, val test, val keyfun)
return nil;
}
+val hash_keys_of(val hash, val value, val test, val keyfun)
+{
+ val self = lit("hash-keys-of");
+ val cell;
+ struct hash_iter hi;
+ list_collect_decl(out, ptail);
+
+ hash_iter_init(&hi, hash, self);
+
+ test = default_arg(test, eql_f);
+ keyfun = default_arg(keyfun, identity_f);
+
+ while ((cell = hash_iter_next(&hi)) != nil) {
+ if (funcall2(test, value, funcall1(keyfun, us_cdr(cell))))
+ ptail = list_collect(ptail, us_car(cell));
+ }
+
+ return out;
+}
+
val hash_invert(val hash, val joinfun, val unitfun, struct args *hashv_args)
{
val self = lit("hash-invert");
@@ -1916,6 +1936,7 @@ void hash_init(void)
reg_fun(intern(lit("hash-update-1"), user_package),
func_n4o(hash_update_1, 3));
reg_fun(intern(lit("hash-revget"), user_package), func_n4o(hash_revget, 2));
+ reg_fun(intern(lit("hash-keys-of"), user_package), func_n4o(hash_keys_of, 2));
reg_fun(intern(lit("hash-invert"), user_package), func_n3ov(hash_invert, 1));
reg_fun(intern(lit("hash-begin"), user_package), func_n1(hash_begin));
reg_fun(intern(lit("hash-next"), user_package), func_n1(hash_next));
diff --git a/hash.h b/hash.h
index f9fcb75b..542b3e1a 100644
--- a/hash.h
+++ b/hash.h
@@ -89,6 +89,7 @@ val hash_proper_subset(val hash1, val hash2);
val hash_update(val hash, val fun);
val hash_update_1(val hash, val key, val fun, val init);
val hash_revget(val hash, val value, val test, val keyfun);
+val hash_keys_of(val hash, val value, val test, val keyfun);
val hash_invert(val hash, val joinfun, val unitfun, struct args *hashv_args);
void hash_process_weak(void);
diff --git a/txr.1 b/txr.1
index 54550b31..bf1233e2 100644
--- a/txr.1
+++ b/txr.1
@@ -48244,9 +48244,10 @@ to
The function returns
.codn nil .
-.coNP Function @ hash-revget
+.coNP Functions @ hash-revget and @ hash-keys-of
.synb
.mets (hash-revget < hash < value >> [ testfun <> [ keyfun ]])
+.mets (hash-keys-of < hash < value >> [ testfun <> [ keyfun ]])
.syne
.desc
The
@@ -48268,6 +48269,14 @@ If multiple matching entries exist, it is not specified which entry's
key is returned.
The
+.code hash-keys-of
+function has exactly the same argument conventions, and likewise
+searches the
+.metn hash .
+However, it returns a list of all keys whose values match
+.metn value .
+
+The
.meta keyfun
function is applied to each value in
.meta hash