Skip to content

Commit 5a83e3a

Browse files
committed
Add mutable union and difference operations on sets
1 parent 5bfcb1a commit 5a83e3a

File tree

3 files changed

+128
-9
lines changed

3 files changed

+128
-9
lines changed

docs/new_sets_doc.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,29 @@ Returns the union of several sets.
246246
The set union of all sets in `*args`.
247247

248248

249+
<a id="sets.mutable_union"></a>
250+
251+
## sets.mutable_union
252+
253+
<pre>
254+
sets.mutable_union(<a href="#sets.mutable_union-a">a</a>, <a href="#sets.mutable_union-b">b</a>)
255+
</pre>
256+
257+
Modify set `a` adding elements from `b` to it.
258+
259+
**PARAMETERS**
260+
261+
262+
| Name | Description | Default Value |
263+
| :------------- | :------------- | :------------- |
264+
| <a id="sets.mutable_union-a"></a>a | A set, as returned by <code>sets.make()</code>. | none |
265+
| <a id="sets.mutable_union-b"></a>b | A set, as returned by <code>sets.make()</code>. | none |
266+
267+
**RETURNS**
268+
269+
The set `a` with all elements appearing in `b` added to it.
270+
271+
249272
<a id="sets.difference"></a>
250273

251274
## sets.difference
@@ -269,6 +292,29 @@ Returns the elements in `a` that are not in `b`.
269292
A set containing the elements that are in `a` but not in `b`.
270293

271294

295+
<a id="sets.mutable_difference"></a>
296+
297+
## sets.mutable_difference
298+
299+
<pre>
300+
sets.mutable_difference(<a href="#sets.mutable_difference-a">a</a>, <a href="#sets.mutable_difference-b">b</a>)
301+
</pre>
302+
303+
Modify set `a` removing elements from `b` from it.
304+
305+
**PARAMETERS**
306+
307+
308+
| Name | Description | Default Value |
309+
| :------------- | :------------- | :------------- |
310+
| <a id="sets.mutable_difference-a"></a>a | A set, as returned by <code>sets.make()</code>. | none |
311+
| <a id="sets.mutable_difference-b"></a>b | A set, as returned by <code>sets.make()</code>. | none |
312+
313+
**RETURNS**
314+
315+
The set `a` with all elements appearing in `b` removed from it.
316+
317+
272318
<a id="sets.length"></a>
273319

274320
## sets.length

lib/new_sets.bzl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,19 @@ def _union(*args):
189189
"""
190190
return struct(_values = dicts.add(*[s._values for s in args]))
191191

192+
def _mutable_union(a, b):
193+
"""Modify set `a` adding elements from `b` to it.
194+
195+
Args:
196+
a: A set, as returned by `sets.make()`.
197+
b: A set, as returned by `sets.make()`.
198+
199+
Returns:
200+
The set `a` with all elements appearing in `b` added to it.
201+
"""
202+
a._values.update(b._values)
203+
return a
204+
192205
def _difference(a, b):
193206
"""Returns the elements in `a` that are not in `b`.
194207
@@ -201,6 +214,20 @@ def _difference(a, b):
201214
"""
202215
return struct(_values = {e: None for e in a._values.keys() if e not in b._values})
203216

217+
def _mutable_difference(a, b):
218+
"""Modify set `a` removing elements from `b` from it.
219+
220+
Args:
221+
a: A set, as returned by `sets.make()`.
222+
b: A set, as returned by `sets.make()`.
223+
224+
Returns:
225+
The set `a` with all elements appearing in `b` removed from it.
226+
"""
227+
for item in b._values.keys():
228+
a._values.pop(item)
229+
return a
230+
204231
def _length(s):
205232
"""Returns the number of elements in a set.
206233
@@ -234,7 +261,9 @@ sets = struct(
234261
disjoint = _disjoint,
235262
intersection = _intersection,
236263
union = _union,
264+
mutable_union = _mutable_union,
237265
difference = _difference,
266+
mutable_difference = _mutable_difference,
238267
length = _length,
239268
remove = _remove,
240269
repr = _repr,

tests/new_sets_tests.bzl

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,29 @@ def _union_test(ctx):
9898
"""Unit tests for sets.union."""
9999
env = unittest.begin(ctx)
100100

101-
asserts.new_set_equals(env, sets.make(), sets.union())
102-
asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make([1])))
103-
asserts.new_set_equals(env, sets.make(), sets.union(sets.make(), sets.make()))
104-
asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make(), sets.make([1])))
105-
asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make([1]), sets.make()))
106-
asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make([1]), sets.make([1])))
107-
asserts.new_set_equals(env, sets.make([1, 2]), sets.union(sets.make([1]), sets.make([1, 2])))
108-
asserts.new_set_equals(env, sets.make([1, 2]), sets.union(sets.make([1]), sets.make([2])))
101+
s = sets.make()
102+
s = sets.mutable_union(s, sets.make())
103+
asserts.new_set_equals(env, sets.make(), s)
104+
s = sets.make()
105+
s = sets.mutable_union(s, sets.make([1]))
106+
asserts.new_set_equals(env, sets.make([1]), s)
107+
s = sets.make([1])
108+
s = sets.mutable_union(s, sets.make())
109+
asserts.new_set_equals(env, sets.make([1]), s)
110+
s = sets.make([1])
111+
s = sets.mutable_union(s, sets.make([1]))
112+
asserts.new_set_equals(env, sets.make([1]), s)
113+
s = sets.make([1])
114+
s = sets.mutable_union(s, sets.make([1, 2]))
115+
asserts.new_set_equals(env, sets.make([1, 2]), s)
116+
s = sets.make([1])
117+
s = sets.mutable_union(s, sets.make([2]))
118+
asserts.new_set_equals(env, sets.make([1, 2]), s)
109119

110120
# If passing a list, verify that duplicate elements are ignored.
111-
asserts.new_set_equals(env, sets.make([1, 2]), sets.union(sets.make([1, 1]), sets.make([1, 2])))
121+
s = sets.make([1, 1])
122+
s = sets.mutable_union(s, sets.make([1, 2]))
123+
asserts.new_set_equals(env, sets.make([1, 2]), s)
112124

113125
return unittest.end(env)
114126

@@ -132,6 +144,38 @@ def _difference_test(ctx):
132144

133145
difference_test = unittest.make(_difference_test)
134146

147+
def _mutable_difference_test(ctx):
148+
"""Unit tests for sets.difference."""
149+
env = unittest.begin(ctx)
150+
151+
s = sets.make()
152+
s = sets.mutable_difference(s, sets.make())
153+
asserts.new_set_equals(env, sets.make(), s)
154+
s = sets.make()
155+
s = sets.mutable_difference(s, sets.make([1]))
156+
asserts.new_set_equals(env, sets.make(), s)
157+
s = sets.make([1])
158+
s = sets.mutable_difference(s, sets.make())
159+
asserts.new_set_equals(env, sets.make([1]), s)
160+
s = sets.make([1])
161+
s = sets.mutable_difference(s, sets.make([1]))
162+
asserts.new_set_equals(env, sets.make(), s)
163+
s = sets.make([1])
164+
s = sets.mutable_difference(s, sets.make([1, 2]))
165+
asserts.new_set_equals(env, sets.make(), s)
166+
s = sets.make([1])
167+
s = sets.mutable_difference(s, sets.make([2]))
168+
asserts.new_set_equals(env, sets.make([1]), s)
169+
170+
# If passing a list, verify that duplicate elements are ignored.
171+
s = sets.make([1, 2])
172+
s = s.mutable_difference(s, sets.make([1, 1]))
173+
asserts.new_set_equals(env, sets.make([2]), s)
174+
175+
return unittest.end(env)
176+
177+
mutable_difference_test = unittest.make(_mutable_difference_test)
178+
135179
def _to_list_test(ctx):
136180
"""Unit tests for sets.to_list."""
137181
env = unittest.begin(ctx)

0 commit comments

Comments
 (0)