Skip to content

Commit 13844dd

Browse files
committed
Add map functions to check for equality of keys
This is done because map key equality does not work for maps, arrays, tuples, or anything else not a number, string or symbol fixes #406
1 parent b8f2478 commit 13844dd

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

src/javascript/lib/core/erlang_compat/maps.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,62 @@ const ERROR = Symbol.for('error');
77
const BADMAP = Symbol.for('badmap');
88
const BADKEY = Symbol.for('badkey');
99

10+
function is_non_primitive(key) {
11+
return (
12+
erlang.is_list(key) ||
13+
erlang.is_map(key) ||
14+
erlang.is_pid(key) ||
15+
erlang.is_reference(key) ||
16+
erlang.is_bitstring(key)
17+
);
18+
}
19+
20+
function __has(map, key) {
21+
if (is_non_primitive(key)) {
22+
for (const map_key of map.keys()) {
23+
if (erlang.equals(map_key, key)) {
24+
return true;
25+
}
26+
}
27+
28+
return false;
29+
}
30+
31+
return map.has(key);
32+
}
33+
34+
function __get(map, key) {
35+
if (is_non_primitive(key)) {
36+
for (const map_key of map.keys()) {
37+
if (erlang.equals(map_key, key)) {
38+
return map.get(map_key);
39+
}
40+
}
41+
42+
return null;
43+
}
44+
45+
return map.get(key);
46+
}
47+
48+
function __delete(map, key) {
49+
if (is_non_primitive(key)) {
50+
for (const map_key of map.keys()) {
51+
if (erlang.equals(map_key, key)) {
52+
map.delete(map_key);
53+
}
54+
}
55+
} else {
56+
map.delete(key);
57+
}
58+
}
59+
1060
function find(key, map) {
1161
if (erlang.is_map(map) === false) {
1262
return new ErlangTypes.Tuple(BADMAP, map);
1363
}
1464

15-
const value = map.get(key);
65+
const value = __get(map, key);
1666

1767
if (typeof value !== 'undefined') {
1868
return new ErlangTypes.Tuple(OK, value);
@@ -38,7 +88,7 @@ function remove(key, map1) {
3888

3989
const map2 = new Map(map1);
4090

41-
map2.delete(key);
91+
__delete(map2, key);
4292

4393
return map2;
4494
}
@@ -83,7 +133,7 @@ function values(map) {
83133
}
84134

85135
function is_key(key, map) {
86-
return map.has(key);
136+
return __has(map, key);
87137
}
88138

89139
function put(key, value, map1) {
@@ -130,7 +180,7 @@ function get(...args) {
130180
}
131181

132182
if (is_key(key)) {
133-
return map.get(key);
183+
return __get(map, key);
134184
}
135185

136186
if (args.length === 3) {
@@ -149,9 +199,9 @@ function take(key, map1) {
149199
return ERROR;
150200
}
151201

152-
const value = map1.get(key);
202+
const value = __get(map1, key);
153203
const map2 = new Map(map1);
154-
map2.delete(key);
204+
__delete(map2, key);
155205

156206
return new ErlangTypes.Tuple(value, map2);
157207
}
@@ -170,4 +220,5 @@ export default {
170220
update,
171221
get,
172222
take,
223+
__has,
173224
};

src/javascript/tests/core/erlang_compat/maps_spec.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,37 @@ test('find', (t) => {
1313
myMap = new Map([['t', 'b']]);
1414
result = Core.maps.find('t', myMap);
1515
t.deepEqual(result.values, [Symbol.for('ok'), 'b']);
16+
17+
myMap = new Map([[[1], 'b']]);
18+
result = Core.maps.find([1], myMap);
19+
t.deepEqual(result.values, [Symbol.for('ok'), 'b']);
20+
21+
myMap = new Map([[new Map(), 'b']]);
22+
result = Core.maps.find(new Map(), myMap);
23+
t.deepEqual(result.values, [Symbol.for('ok'), 'b']);
1624
});
1725

1826
test('fold', (t) => {
1927
const myMap = new Map([['a', 1], ['b', 2]]);
2028
const result = Core.maps.fold((k, v, acc) => acc + v, 0, myMap);
2129
t.is(result, 3);
2230
});
31+
32+
test('is_key', (t) => {
33+
const myMap = new Map([['a', 1], ['b', 2]]);
34+
let result = Core.maps.is_key('a', myMap);
35+
t.is(result, true);
36+
37+
result = Core.maps.is_key('c', myMap);
38+
t.is(result, false);
39+
});
40+
41+
test('remove', (t) => {
42+
let myMap = new Map([['a', 1], ['b', 2]]);
43+
let result = Core.maps.remove('a', myMap);
44+
t.is(result.has('a'), false);
45+
46+
myMap = new Map([[[1], 1], ['b', 2]]);
47+
result = Core.maps.remove([1], myMap);
48+
t.is(Core.maps.__has(result, [1]), false);
49+
});

0 commit comments

Comments
 (0)