summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hash.c38
-rw-r--r--hash.h2
-rw-r--r--tests/010/hash.tl7
-rw-r--r--txr.147
4 files changed, 91 insertions, 3 deletions
diff --git a/hash.c b/hash.c
index e4c23321..84b27fde 100644
--- a/hash.c
+++ b/hash.c
@@ -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));
diff --git a/hash.h b/hash.h
index 68708699..858a4c28 100644
--- a/hash.h
+++ b/hash.h
@@ -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)
diff --git a/txr.1 b/txr.1
index 88d18692..cbecdee2 100644
--- a/txr.1
+++ b/txr.1
@@ -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 )