summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--lib/std/setutils.nim20
-rw-r--r--tests/stdlib/tsetutils.nim11
3 files changed, 29 insertions, 4 deletions
diff --git a/changelog.md b/changelog.md
index d0ad8e8e4..906676fb0 100644
--- a/changelog.md
+++ b/changelog.md
@@ -89,7 +89,7 @@
   if the iterable yields a built-in settable type.
 - Added `setutils.fullSet` which returns a full built-in `set` for a valid type.
 - Added `setutils.complement` which returns the complement of a built-in `set`.
-
+- Added `setutils.[]=`.
 
 - Added `math.isNaN`.
 
diff --git a/lib/std/setutils.nim b/lib/std/setutils.nim
index d5d60d4ab..c7fac0a54 100644
--- a/lib/std/setutils.nim
+++ b/lib/std/setutils.nim
@@ -38,8 +38,8 @@ template toSet*(iter: untyped): untyped =
 
 macro enmRange(enm: typed): untyped = result = newNimNode(nnkCurly).add(enm.getType[1][1..^1])
 
-# proc fullSet*(T: typedesc): set[T] {.inline.} = # xxx would give: Error: ordinal type expected
-proc fullSet*[T](U: typedesc[T]): set[T] {.inline.} =
+# func fullSet*(T: typedesc): set[T] {.inline.} = # xxx would give: Error: ordinal type expected
+func fullSet*[T](U: typedesc[T]): set[T] {.inline.} =
   ## Returns a set containing all elements in `U`.
   runnableExamples:
     assert bool.fullSet == {true, false}
@@ -51,7 +51,7 @@ proc fullSet*[T](U: typedesc[T]): set[T] {.inline.} =
   else: # Hole filled enum
     enmRange(T)
 
-proc complement*[T](s: set[T]): set[T] {.inline.} =
+func complement*[T](s: set[T]): set[T] {.inline.} =
   ## Returns the set complement of `a`.
   runnableExamples:
     type Colors = enum
@@ -61,3 +61,17 @@ proc complement*[T](s: set[T]): set[T] {.inline.} =
     assert complement({range[0..10](0), 1, 2, 3}) == {range[0..10](4), 5, 6, 7, 8, 9, 10}
     assert complement({'0'..'9'}) == {0.char..255.char} - {'0'..'9'}
   fullSet(T) - s
+
+func `[]=`*[T](t: var set[T], key: T, val: bool) {.inline.} =
+  ## Syntax sugar for `if val: t.incl key else: t.excl key`
+  runnableExamples:
+    type A = enum
+      a0, a1, a2, a3
+    var s = {a0, a3}
+    s[a0] = false
+    s[a1] = false
+    assert s == {a3}
+    s[a2] = true
+    s[a3] = true
+    assert s == {a2, a3}
+  if val: t.incl key else: t.excl key
diff --git a/tests/stdlib/tsetutils.nim b/tests/stdlib/tsetutils.nim
index d5093bf11..f2fb81e6a 100644
--- a/tests/stdlib/tsetutils.nim
+++ b/tests/stdlib/tsetutils.nim
@@ -32,5 +32,16 @@ template main =
     doAssert {range[0..10](0), 1, 2, 3}.complement == {range[0..10](4), 5, 6, 7, 8, 9, 10}
     doAssert {'0'..'9'}.complement == {0.char..255.char} - {'0'..'9'}
 
+  block: # `[]=`
+    type A = enum
+      a0, a1, a2, a3
+    var s = {a0, a3}
+    s[a0] = false
+    s[a1] = false
+    doAssert s == {a3}
+    s[a2] = true
+    s[a3] = true
+    doAssert s == {a2, a3}
+
 main()
 static: main()