summaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-10-28 07:02:50 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-10-28 07:02:50 -0700
commitdff12605926554d9aa76c4f80c8adc0ee82fa2bb (patch)
treef4264179e4ae080ab3ad9b9e56ef6e454a9770a6 /hash.c
parent374509f247df16d40d2535a34237fa2f5dd5863e (diff)
downloadtxr-dff12605926554d9aa76c4f80c8adc0ee82fa2bb.tar.gz
txr-dff12605926554d9aa76c4f80c8adc0ee82fa2bb.tar.bz2
txr-dff12605926554d9aa76c4f80c8adc0ee82fa2bb.zip
New function: hash-invert.
* hash.c (hash_invert): New function. (hash_init): hash-invert intrinsic registered. * hash.c (hash_invert): Declared. * txr.1: Documented.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/hash.c b/hash.c
index 27d62dba..e85efa03 100644
--- a/hash.c
+++ b/hash.c
@@ -1735,6 +1735,36 @@ val hash_revget(val hash, val value, val test, val keyfun)
return nil;
}
+val hash_invert(val hash, val joinfun, val unitfun, struct args *hashv_args)
+{
+ val self = lit("hash-invert");
+ val hout = hashv(hashv_args);
+ val iter = hash_begin(hash);
+ val jfun = default_arg(joinfun, identity_star_f);
+ val ufun = default_arg(unitfun, identity_f);
+ val cell;
+
+ if (jfun == identity_star_f && ufun == identity_f) {
+ while ((cell = hash_next(iter)) != nil) {
+ us_cons_bind(k, v, cell);
+ sethash(hout, v, k);
+ }
+ } else {
+ while ((cell = hash_next(iter)) != nil) {
+ us_cons_bind(k, v, cell);
+ val new_p;
+ loc place = gethash_l(self, hout, v, mkcloc(new_p));
+ val ukey = funcall1(ufun, k);
+ if (new_p)
+ set(place, ukey);
+ else
+ set(place, funcall2(jfun, deref(place), ukey));
+ }
+ }
+
+ return hout;
+}
+
static val set_hash_traversal_limit(val lim)
{
val old = num(hash_traversal_limit);
@@ -1809,6 +1839,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-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));
reg_fun(intern(lit("hash-peek"), user_package), func_n1(hash_peek));