summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Perehonchuk <romanp@meta.com>2024-10-01 06:01:42 -0700
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>2024-10-01 06:01:42 -0700
commitc5dba245b10fce680c5d9abdffd65c0d91ef0427 (patch)
treedf7ff44ef9d4c33d60daeb7b0588d60bc16a7a56
parent372abd484ec8f7862032713e00582c64056de396 (diff)
sub for sets
Summary: as per title Reviewed By: stepancheg Differential Revision: D63471534 fbshipit-source-id: 31da09aa94f614d102938643ffa686b564205c8e
-rw-r--r--starlark/src/values/types/set/value.rs51
-rw-r--r--starlark/testcases/eval/go/set.star4
2 files changed, 53 insertions, 2 deletions
diff --git a/starlark/src/values/types/set/value.rs b/starlark/src/values/types/set/value.rs
index c2c23d8a..29046099 100644
--- a/starlark/src/values/types/set/value.rs
+++ b/starlark/src/values/types/set/value.rs
@@ -317,6 +317,34 @@ where
}
Ok(heap.alloc(data))
}
+
+ // Set difference
+ //TODO(romanp) implement difference on small_set level and reuse it here and in difference function
+ fn sub(&self, rhs: Value<'v>, heap: &'v Heap) -> crate::Result<Value<'v>> {
+ let rhs = SetRef::from_value(rhs)
+ .map_or_else(|| ValueError::unsupported_with(self, "-", rhs), Ok)?;
+
+ if self.0.content().is_empty() {
+ return Ok(heap.alloc(SetData {
+ content: SmallSet::new(),
+ }));
+ }
+
+ if rhs.content.is_empty() {
+ return Ok(heap.alloc(SetData {
+ content: self.0.content().clone(),
+ }));
+ }
+
+ let mut data = SetData::default();
+
+ for elem in self.0.content().iter_hashed() {
+ if !rhs.contains_hashed(elem.copied()) {
+ data.add_hashed(elem.copied());
+ }
+ }
+ Ok(heap.alloc(data))
+ }
}
impl<'v, T: SetLike<'v>> Serialize for SetGen<T> {
@@ -421,4 +449,27 @@ mod tests {
"Operation `^` not supported for types `set` and `list`",
);
}
+
+ #[test]
+ fn test_sub() {
+ assert::eq("set([1, 2, 3]) - set([2])", "set([1, 3])")
+ }
+
+ #[test]
+ fn test_sub_empty_lhs() {
+ assert::eq("set([]) - set([2])", "set([])")
+ }
+
+ #[test]
+ fn test_sub_empty_rhs() {
+ assert::eq("set([1, 2]) - set([])", "set([2, 1])")
+ }
+
+ #[test]
+ fn test_sub_fail_iter() {
+ assert::fail(
+ "set([1, 2, 3]) - []",
+ "Operation `-` not supported for types `set` and `list`",
+ );
+ }
}
diff --git a/starlark/testcases/eval/go/set.star b/starlark/testcases/eval/go/set.star
index b030bd9d..28a11e4e 100644
--- a/starlark/testcases/eval/go/set.star
+++ b/starlark/testcases/eval/go/set.star
@@ -173,8 +173,8 @@ asserts.eq(set([1,2,3,4]).difference([1,2]), set([3,4]))
asserts.eq(set([1,2,3,4]).difference([]), set([1,2,3,4]))
asserts.eq(set([1,2,3,4]).difference(set([1,2,3])), set([4]))
-# asserts.eq(set([1,2,3,4]) - set([1,2,3,4]), set())
-# asserts.eq(set([1,2,3,4]) - set([1,2]), set([3,4]))
+asserts.eq(set([1,2,3,4]) - set([1,2,3,4]), set())
+asserts.eq(set([1,2,3,4]) - set([1,2]), set([3,4]))
# # issuperset: set >= set or set.issuperset(iterable)
# asserts.true(set([1,2,3]).issuperset([1,2]))