diff options
-rw-r--r-- | hash.c | 38 | ||||
-rw-r--r-- | hash.h | 2 | ||||
-rw-r--r-- | tests/010/hash.tl | 7 | ||||
-rw-r--r-- | txr.1 | 47 |
4 files changed, 91 insertions, 3 deletions
@@ -1766,6 +1766,21 @@ val hash_list(val keys, varg hashv_args) return hash; } +val hash_seq(val keys, struct args *hashv_args) +{ + val self = lit("hash-seq"); + val hash = hashv(hashv_args); + seq_iter_t iter; + val elem; + + seq_iter_init(self, &iter, keys); + + while (seq_get(&iter, &elem)) + sethash(hash, elem, elem); + + return hash; +} + val hash_zip(val keys, val vals, varg hashv_args) { val self = lit("hash-zip"); @@ -2089,6 +2104,27 @@ val hash_isec(val hash1, val hash2, val joinfun) } } +val hash_isecp(val hash1, val hash2) +{ + val self = lit("hash-isecp"); + struct hash *h1 = coerce(struct hash *, cobj_handle(self, hash1, hash_cls)); + struct hash *h2 = coerce(struct hash *, cobj_handle(self, hash2, hash_cls)); + + { + val entry; + struct hash_iter hi; + + hash_iter_init(&hi, hash1, self); + + for (entry = hash_iter_next(&hi); entry; entry = hash_iter_next(&hi)) { + if (gethash_e(self, hash2, us_car(entry))) + return t; + } + + return nil; + } +} + val hash_subset(val hash1, val hash2) { val self = lit("hash-subset"); @@ -2286,6 +2322,7 @@ void hash_init(void) reg_fun(intern(lit("hash-map"), user_package), func_n2v(hash_map)); reg_fun(intern(lit("hash-props"), user_package), func_n0v(hash_props)); reg_fun(intern(lit("hash-list"), user_package), func_n1v(hash_list)); + reg_fun(intern(lit("hash-seq"), user_package), func_n1v(hash_seq)); reg_fun(intern(lit("hash-zip"), user_package), func_n2v(hash_zip)); reg_fun(intern(lit("gethash"), user_package), func_n3o(gethash_n, 2)); reg_fun(intern(lit("inhash"), user_package), func_n3o(inhash, 2)); @@ -2311,6 +2348,7 @@ void hash_init(void) 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)); + reg_fun(intern(lit("hash-isecp"), user_package), func_n2(hash_isecp)); reg_fun(intern(lit("hash-subset"), user_package), func_n2(hash_subset)); reg_fun(intern(lit("hash-proper-subset"), user_package), func_n2(hash_proper_subset)); reg_fun(intern(lit("group-by"), user_package), func_n2v(group_by)); @@ -88,6 +88,7 @@ val hash_from_alist_v(val alist, struct args *hashv_args); val hash_map(val fun, val seq, struct args *hashv_args); val hash_props(struct args *plist); val hash_list(val keys, struct args *hashv_args); +val hash_seq(val keys, struct args *hashv_args); val hash_zip(val keys, val vals, struct args *hashv_args); val group_by(val func, val seq, struct args *hashv_args); val group_map(val by_fun, val filter_fun, val seq, struct args *hashv_args); @@ -102,6 +103,7 @@ val hash_join(val hash1, val hash2, val joinfun, val h1dfl, val h2dfl); val hash_diff(val hash1, val hash2); val hash_symdiff(val hash1, val hash2); val hash_isec(val hash1, val hash2, val joinfun); +val hash_isecp(val hash1, val hash2); val hash_subset(val hash1, val hash2); val hash_proper_subset(val hash1, val hash2); val hash_update(val hash, val fun); diff --git a/tests/010/hash.tl b/tests/010/hash.tl index bd37e180..f8915e11 100644 --- a/tests/010/hash.tl +++ b/tests/010/hash.tl @@ -103,3 +103,10 @@ (hash-next hi2) (hash-next hi1) (hash-next hi1) nil (hash-next hi2) nil)) + +(test (hash-seq 0..6) #H(() (0 0) (1 1) (2 2) (3 3) (4 4) (5 5))) + +(mtest + (hash-isecp #H() #H()) nil + (hash-isecp #H(() (a 1)) #H(() (b 1))) nil + (hash-isecp #H(() (a 1) (c 1)) #H(() (b 1) (c 2))) t) @@ -60657,14 +60657,17 @@ is a key, and whose .code cdr is the value. -.coNP Function @ hash-list +.coNP Functions @ hash-list and @ hash-seq .synb .mets (hash-list < key-list << hash-arg *) +.mets (hash-seq < key-seq << hash-arg *) .syne .desc The .code hash-list -function constructs a hash as if by a call to +and +.code hash-seq +functions construct a hash as if by a call to .mono .meti [apply hash << hash-args ], .onom @@ -60676,10 +60679,26 @@ variadic arguments. The hash is then populated with keys taken from .meta key-list +or +.meta key-seq and returned. The value associated with each key is that key itself. +The +.code hash-list +function traverses +.code key-list +using the +.code cdr +function and accesses key values using +.codn car , +whereas the +.code hash-seq +function uses abstract iteration as if using functions in the +.code iter-begin +family. + .coNP Function @ hash-zip .synb .mets (hash-zip < key-seq < value-seq << hash-arg *) @@ -61717,10 +61736,14 @@ or .mets (hash-diff < hash1 << hash2 ) .mets (hash-symdiff < hash1 << hash2 ) .mets (hash-isec < hash1 < hash2 <> [ joinfun ]) +.mets (hash-isecp < hash1 << hash2 ) .syne .desc These functions perform basic set operations on hash tables in a nondestructive -way, returning a new hash table without altering the inputs. The arguments +way, returning a new hash table without altering the inputs. Except in the +case of the +.code hash-isecp +function, the arguments .meta hash1 and .meta hash2 @@ -61874,6 +61897,24 @@ and it is called with two arguments: the respective data items. The return value is then used as the data item in the intersection hash. +The +.code hash-isecp +function performs an intersection test without computing the intersection. If +any key of +.meta hash1 +is found in +.meta hash2 +then the function returns +.codn t , +otherwise +.codn nil . +For the purposes of +.codn hash-isecp , +.meta hash1 +and +.meta hash2 +do not have to be compatible hashes. + .coNP Functions @ hash-subset and @ hash-proper-subset .synb .mets (hash-subset < hash1 << hash2 ) |