Skip to content

Commit 771954f

Browse files
committed
pymap: Streamline .assoc() method
1 parent 4049542 commit 771954f

File tree

2 files changed

+23
-27
lines changed

2 files changed

+23
-27
lines changed

immutables/map.py

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def __init__(self, size, bitmap, array):
5252
def clone(self):
5353
return BitmapNode(self.size, self.bitmap, self.array.copy())
5454

55-
def assoc(self, shift, hash, key, val, added_leaf):
55+
def assoc(self, shift, hash, key, val):
5656
bit = map_bitpos(hash, shift)
5757
idx = map_bitindex(self.bitmap, bit)
5858

@@ -64,44 +64,41 @@ def assoc(self, shift, hash, key, val, added_leaf):
6464
val_or_node = self.array[val_idx]
6565

6666
if key_or_null is None:
67-
sub_node = val_or_node.assoc(
68-
shift + 5, hash, key, val, added_leaf)
67+
sub_node, added = val_or_node.assoc(
68+
shift + 5, hash, key, val)
6969
if val_or_node is sub_node:
70-
return self
70+
return self, False
7171

7272
ret = self.clone()
7373
ret.array[val_idx] = sub_node
74-
return ret
74+
return ret, added
7575

7676
if key == key_or_null:
7777
if val is val_or_node:
78-
return self
78+
return self, False
7979

8080
ret = self.clone()
8181
ret.array[val_idx] = val
82-
return ret
82+
return ret, False
8383

8484
existing_key_hash = map_hash(key_or_null)
8585
if existing_key_hash == hash:
8686
sub_node = CollisionNode(
8787
4, hash, [key_or_null, val_or_node, key, val])
8888
else:
8989
sub_node = BitmapNode(0, 0, [])
90-
sub_node = sub_node.assoc(
90+
sub_node, _ = sub_node.assoc(
9191
shift + 5, existing_key_hash,
92-
key_or_null, val_or_node, [False])
93-
sub_node = sub_node.assoc(
94-
shift + 5, hash, key, val, [False])
92+
key_or_null, val_or_node)
93+
sub_node, _ = sub_node.assoc(
94+
shift + 5, hash, key, val)
9595

9696
ret = self.clone()
9797
ret.array[key_idx] = None
9898
ret.array[val_idx] = sub_node
99-
added_leaf[0] = True
100-
return ret
99+
return ret, True
101100

102101
else:
103-
added_leaf[0] = True
104-
105102
key_idx = 2 * idx
106103
val_idx = key_idx + 1
107104

@@ -111,7 +108,7 @@ def assoc(self, shift, hash, key, val, added_leaf):
111108
new_array.append(key)
112109
new_array.append(val)
113110
new_array.extend(self.array[key_idx:])
114-
return BitmapNode(2 * (n + 1), self.bitmap | bit, new_array)
111+
return BitmapNode(2 * (n + 1), self.bitmap | bit, new_array), True
115112

116113
def find(self, shift, hash, key):
117114
bit = map_bitpos(hash, shift)
@@ -251,7 +248,7 @@ def find(self, shift, hash, key):
251248
return self.array[i + 1]
252249
raise KeyError(key)
253250

254-
def assoc(self, shift, hash, key, val, added_leaf):
251+
def assoc(self, shift, hash, key, val):
255252
if hash == self.hash:
256253
key_idx = self.find_index(key)
257254

@@ -260,21 +257,20 @@ def assoc(self, shift, hash, key, val, added_leaf):
260257
new_array.append(key)
261258
new_array.append(val)
262259
new_node = CollisionNode(self.size + 2, hash, new_array)
263-
added_leaf[0] = True
264-
return new_node
260+
return new_node, True
265261

266262
val_idx = key_idx + 1
267263
if self.array[val_idx] is val:
268-
return self
264+
return self, False
269265

270266
new_array = self.array.copy()
271267
new_array[val_idx] = val
272-
return CollisionNode(self.size, hash, new_array)
268+
return CollisionNode(self.size, hash, new_array), False
273269

274270
else:
275271
new_node = BitmapNode(
276272
2, map_bitpos(self.hash, shift), [None, self])
277-
return new_node.assoc(shift, hash, key, val, added_leaf)
273+
return new_node.assoc(shift, hash, key, val)
278274

279275
def without(self, shift, hash, key):
280276
if hash != self.hash:
@@ -375,16 +371,14 @@ def __eq__(self, other):
375371
return True
376372

377373
def set(self, key, val):
378-
added = [False]
379-
380374
new_count = self.__count
381-
new_root = self.__root.assoc(0, map_hash(key), key, val, added)
375+
new_root, added = self.__root.assoc(0, map_hash(key), key, val)
382376

383377
if new_root is self.__root:
384-
assert not added[0]
378+
assert not added
385379
return self
386380

387-
if added[0]:
381+
if added:
388382
new_count += 1
389383

390384
m = Map.__new__(Map)

tests/test_map.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,9 @@ def test_map_delete_3(self):
455455
h = h.set(D, 'd')
456456
h = h.set(E, 'e')
457457

458+
self.assertEqual(len(h), 5)
458459
h = h.set(C, 'c') # trigger branch in CollisionNode.assoc
460+
self.assertEqual(len(h), 5)
459461

460462
orig_len = len(h)
461463

0 commit comments

Comments
 (0)