summaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/hash.c b/hash.c
index cd91ad5e..c74a6294 100644
--- a/hash.c
+++ b/hash.c
@@ -55,6 +55,7 @@ struct hash {
cnum count;
val userdata;
cnum (*hash_fun)(val);
+ val (*equal_fun)(val, val);
val (*assoc_fun)(val key, val list);
val *(*acons_new_l_fun)(val key, val *new_p, val *list);
};
@@ -248,6 +249,14 @@ static val hash_equal_op(val left, val right)
val found;
/*
+ * Short circuit the logic if we have two identical cells;
+ * no need to go through the pending list.
+ */
+
+ if (l->equal_fun(car(lcell), car(rcell)) && equal(cdr(lcell), cdr(rcell)))
+ continue;
+
+ /*
* Try to find a cell matching the left cell on the pending list by key.
* If it is found, and the associated datum is equal, then remove it from
* the list. If it is found and the data is not equal, then we have found
@@ -460,6 +469,7 @@ val make_hash(val weak_keys, val weak_vals, val equal_based)
h->userdata = nil;
h->hash_fun = equal_based ? equal_hash : eql_hash;
+ h->equal_fun = equal_based ? equal : eql;
h->assoc_fun = equal_based ? assoc : assql;
h->acons_new_l_fun = equal_based ? acons_new_l : aconsql_new_l;
@@ -482,6 +492,7 @@ val make_similar_hash(val existing)
h->flags = ex->flags;
h->hash_fun = ex->hash_fun;
+ h->equal_fun = ex->equal_fun;
h->assoc_fun = ex->assoc_fun;
h->acons_new_l_fun = ex->acons_new_l_fun;