summary refs log tree commit diff stats
path: root/lib/system/setops.nim
blob: 755eafdb81b78dcc7aa3b726e419fcd1c37d6fce (plain) (blame)
1
2
3
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no {
func incl*[T](x: var set[T], y: T) {.magic: "Incl".} =
  ## Includes element `y` in the set `x`.
  ##
  ## This is the same as `x = x + {y}`, but it might be more efficient.
  runnableExamples:
    var a = {1, 3, 5}
    a.incl(2)
    assert a == {1, 2, 3, 5}
    a.incl(4)
    assert a == {1, 2, 3, 4, 5}

template incl*[T](x: var set[T], y: set[T]) =
  ## Includes the set `y` in the set `x`.
  runnableExamples:
    var a = {1, 3, 5, 7}
    var b = {4, 5, 6}
    a.incl(b)
    assert a == {1, 3, 4, 5, 6, 7}
  x = x + y

func excl*[T](x: var set[T], y: T) {.magic: "Excl".} =
  ## Excludes element `y` from the set `x`.
  ##
  ## This is the same as `x = x - {y}`, but it might be more efficient.
  runnableExamples:
    var b = {2, 3, 5, 6, 12, 545}
    b.excl(5)
    assert b == {2, 3, 6, 12, 545}

template excl*[T](x: var set[T], y: set[T]) =
  ## Excludes the set `y` from the set `x`.
  runnableExamples:
    var a = {1, 3, 5, 7}
    var b = {3, 4, 5}
    a.excl(b) 
    assert a == {1, 7}
  x = x - y

func card*[T](x: set[T]): int {.magic: "Card".} =
  ## Returns the cardinality of the set `x`, i.e. the number of elements
  ## in the set.
  runnableExamples:
    var a = {1, 3, 5, 7}
    assert card(a) == 4
    var b = {1, 3, 5, 7, 5}
    assert card(b) == 4 # repeated 5 doesn't count

func len*[T](x: set[T]): int {.magic: "Card".}
  ## An alias for `card(x)`.


func `*`*[T](x, y: set[T]): set[T] {.magic: "MulSet".} =
  ## This operator computes the intersection of two sets.
  runnableExamples:
    assert {1, 2, 3} * {2, 3, 4} == {2, 3}

func `+`*[T](x, y: set[T]): set[T] {.magic: "PlusSet".} =
  ## This operator computes the union of two sets.
  runnableExamples:
    assert {1, 2, 3} + {2, 3, 4} == {1, 2, 3, 4}

func `-`*[T](x, y: set[T]): set[T] {.magic: "MinusSet".} =
  ## This operator computes the difference of two sets.
  runnableExamples:
    assert {1, 2, 3} - {2, 3, 4} == {1}

func contains*[T](x: set[T], y: T): bool {.magic: "InSet".} =
  ## One should overload this proc if one wants to overload the `in` operator.
  ##
  ## The parameters are in reverse order! `a in b` is a template for
  ## `contains(b, a)`.
  ## This is because the unification algorithm that Nim uses for overload
  ## resolution works from left to right.
  ## But for the `in` operator that would be the wrong direction for this
  ## piece of code:
  runnableExamples:
    var s: set[range['a'..'z']] = {'a'..'c'}
    assert s.contains('c')
    assert 'b' in s
    assert 'd' notin s
    assert set['a'..'z'] is set[range['a'..'z']]
  ## If `in` had been declared as `[T](elem: T, s: set[T])` then `T` would
  ## have been bound to `char`. But `s` is not compatible to type
  ## `set[char]`! The solution is to bind `T` to `range['a'..'z']`. This
  ## is achieved by reversing the parameters for `contains`; `in` then
  ## passes its arguments in reverse order.