Skip to content

Commit ac586b1

Browse files
committed
Optimise dict equality check on JavaScript
1 parent c339a97 commit ac586b1

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- Comparing two `Dict`s of equal size has been optimised on the JavaScript
6+
target.
7+
38
## v0.45.0 - 2024-11-28
49

510
- The performance of `string.trim`, `string.trim_start`, and `string.trim_end`

src/dict.mjs

+19-5
Original file line numberDiff line numberDiff line change
@@ -968,10 +968,24 @@ export default class Dict {
968968
if (!(o instanceof Dict) || this.size !== o.size) {
969969
return false;
970970
}
971-
let equal = true;
972-
this.forEach((v, k) => {
973-
equal = equal && isEqual(o.get(k, !v), v);
974-
});
975-
return equal;
971+
972+
try {
973+
this.forEach((v, k) => {
974+
if (!isEqual(o.get(k, !v), v)) {
975+
throw unequalDictSymbol;
976+
}
977+
});
978+
return true;
979+
} catch (e) {
980+
if (e === unequalDictSymbol) {
981+
return false;
982+
}
983+
984+
throw e;
985+
}
976986
}
977987
}
988+
989+
// This is thrown internally in Dict.equals() to return from Dict.equals() as
990+
// soon as a non-matching key is found
991+
const unequalDictSymbol = Symbol();

test/gleam/dict_test.gleam

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ pub fn from_list_test() {
1414
[#(1, 0), #(1, 1)]
1515
|> dict.from_list
1616
|> should.equal(dict.from_list([#(1, 1)]))
17+
18+
[#(1, 0), #(2, 1)]
19+
|> dict.from_list
20+
|> should.not_equal(dict.from_list([#(1, 0), #(2, 2)]))
21+
22+
[#(1, 0), #(2, 1)]
23+
|> dict.from_list
24+
|> should.not_equal(dict.from_list([#(1, 0), #(3, 1)]))
1725
}
1826

1927
pub fn has_key_test() {

0 commit comments

Comments
 (0)