From 380ff399f2c8c0bc514d723a736d2659d34576dc Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 19 Mar 2020 22:41:26 -0700 Subject: hash-uni: two new arguments for projecting values. * hash.c (hash_uni): New functional argument map1fun and map2fun. If present, values from hash1 and hash2, respectively, are projected through these functions. (hash_init): hash-uni registration updated. * hash.h (hash_uni): Declaration updated. * txr.1: Documented new arguments. --- hash.c | 24 ++++++++++++++++-------- hash.h | 2 +- txr.1 | 15 ++++++++++++++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/hash.c b/hash.c index cf3d580c..69b98c1a 100644 --- a/hash.c +++ b/hash.c @@ -1597,7 +1597,7 @@ val hash_alist(val hash) return make_lazy_cons_car(func_f1(iter, hash_alist_lazy), cell); } -val hash_uni(val hash1, val hash2, val joinfun) +val hash_uni(val hash1, val hash2, val joinfun, val map1fun, val map2fun) { val self = lit("hash-uni"); struct hash *h1 = coerce(struct hash *, cobj_handle(self, hash1, hash_s)); @@ -1615,21 +1615,29 @@ val hash_uni(val hash1, val hash2, val joinfun) hash_iter_init(&hi, hash2, self); for (entry = hash_iter_next(&hi); entry; entry = hash_iter_next(&hi)) { - sethash(hout, us_car(entry), us_cdr(entry)); + val rentry = us_cdr(entry); + if (!missingp(map2fun)) + rentry = funcall1(map2fun, rentry); + sethash(hout, us_car(entry), rentry); } hash_iter_init(&hi, hash1, self); for (entry = hash_iter_next(&hi); entry; entry = hash_iter_next(&hi)) { + val lentry = us_cdr(entry); + if (!missingp(map1fun)) + lentry = funcall1(map1fun, lentry); + if (missingp(joinfun)) { - sethash(hout, us_car(entry), us_cdr(entry)); + sethash(hout, us_car(entry), lentry); } else { val new_p; loc ptr = gethash_l(self, hout, us_car(entry), mkcloc(new_p)); - if (new_p) - sethash(hout, us_car(entry), us_cdr(entry)); - else - set(ptr, funcall2(joinfun, us_cdr(entry), deref(ptr))); + if (new_p) { + sethash(hout, us_car(entry), lentry); + } else { + set(ptr, funcall2(joinfun, lentry, deref(ptr))); + } } } @@ -1899,7 +1907,7 @@ void hash_init(void) reg_fun(intern(lit("hash-values"), user_package), func_n1(hash_values)); reg_fun(intern(lit("hash-pairs"), user_package), func_n1(hash_pairs)); reg_fun(intern(lit("hash-alist"), user_package), func_n1(hash_alist)); - reg_fun(intern(lit("hash-uni"), user_package), func_n3o(hash_uni, 2)); + reg_fun(intern(lit("hash-uni"), user_package), func_n5o(hash_uni, 2)); reg_fun(intern(lit("hash-diff"), user_package), func_n2(hash_diff)); reg_fun(intern(lit("hash-symdiff"), user_package), func_n2(hash_symdiff)); reg_fun(intern(lit("hash-isec"), user_package), func_n3o(hash_isec, 2)); diff --git a/hash.h b/hash.h index f6cbf068..e272ce45 100644 --- a/hash.h +++ b/hash.h @@ -80,7 +80,7 @@ val hash_keys(val hash); val hash_values(val hash); val hash_pairs(val hash); val hash_alist(val hash); -val hash_uni(val hash1, val hash2, val joinfun); +val hash_uni(val hash1, val hash2, val joinfun, val lunitfun, val runitfun); val hash_diff(val hash1, val hash2); val hash_symdiff(val hash1, val hash2); val hash_isec(val hash1, val hash2, val joinfun); diff --git a/txr.1 b/txr.1 index 9dd959e8..16360203 100644 --- a/txr.1 +++ b/txr.1 @@ -45819,7 +45819,7 @@ or .coNP Functions @, hash-uni @, hash-diff @ hash-symdiff and @ hash-isec .synb -.mets (hash-uni < hash1 < hash2 <> [ joinfun ]) +.mets (hash-uni < hash1 < hash2 >> [ joinfun >> [ map1fun <> [ map2fun ]]]) .mets (hash-diff < hash1 << hash2 ) .mets (hash-symdiff < hash1 << hash2 ) .mets (hash-isec < hash1 < hash2 <> [ joinfun ]) @@ -45872,6 +45872,19 @@ and .metn hash2 . The return value of this function is used as the value in the union hash. +If +.meta map1fun +is specified it must be a function that can be called with one +argument. All values from +.meta hash1 +are projected through this function: the function is applied +to each value, and the function's return value is used +in place of the original value. +Similarly, if +.meta map2fun +is present, specifies a function through which values from +.meta hash2 +are projected. The .code hash-diff -- cgit v1.2.3