summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/immutable/Set.scala
blob: eadc656470c09ceb67926194b77bb7be1bb11cec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2006, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |                                         **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.collection.immutable


/** This class represents immutable sets. Concrete set implementations
 *  just have to provide functionality for the abstract methods in
 *  <code>scala.collection.Set</code> as well as for <code>+</code> and
 *  <code>-</code>.
 *
 * Note that abstract immutable.Set's are not covariant in their type
 * parameter.  This is because some subclasses cannot support the
 * <code>+</code> method for arbitrary types.
 *
 *  @author  Matthias Zenger
 *  @version 1.1, 03/05/2004
 */
object Set {
  /** The empty set of this type
   */
  def empty[A <% Ordered[A]] = new TreeSet[A]

  /** The canonical factory for this type
   */
  def apply[A <% Ordered[A]](elems: A*) = empty[A] ++ elems
}

trait Set[A] extends AnyRef with collection.Set[A] {

  /** @return an empty set of arbitrary element type
   */
  def empty[B]: Set[B]

  /** Create a new set with an additional element.
   */
  def +(elem: A): Set[A]

  /** Add two or more elements to this set.
   *  @param    elem1 the first element.
   *  @param    elem2 the second element.
   *  @param    elems the remaining elements.
   *  @return a new set with the elements added.
   */
  def + (elem1: A, elem2: A, elems: A*): Set[A] =
    this + elem1 + elem2 ++ elems

  /** Add all the elements provided by an iterator
   *  of the iterable object <code>elems</code> to the set.
   *
   *  @param elems  the iterable object containing the elements to be added
   *  @return a new set with the elements added.
   */
  def ++ (elems: Iterable[A]): Set[A] =
    (this /: elems) ((s, elem) => s + elem)

  /** Add all the elements provided by an iterator to the set.
   *  @param elems  the iterator containing the elements to be added
   *  @return a new set with the elements added.
   */
  def ++ (elems: Iterator[A]): Set[A] =
    (this /: elems) ((s, elem) => s + elem)

  /** <code>incl</code> can be used to add many elements to the set
   *  at the same time.
   */
  [deprecated] def incl(elems: A*): Set[A] = incl(elems)

  /** This method will add all the elements provided by an iterator
   *  of the iterable object <code>that</code> to the set.
   *
   *  @param that ...
   */
  [deprecated] def incl(that: Iterable[A]): Set[A] =
    that.foldLeft(this)((set, elem) => set + elem)

  /** Remove a single element from a set.
   *  @param elem the element to be removed
   *  @return a new set with the element removed.
   */
  def -(elem: A): Set[A]

  /** Remove two or more elements from this set.
   *  @param    elem1 the first element.
   *  @param    elem2 the second element.
   *  @param    elems the remaining elements.
   *  @return a new set with the elements removed.
   */
  def - (elem1: A, elem2: A, elems: A*): Set[A] =
    this - elem1 - elem2 -- elems

  /** Remove all the elements provided by an iterator
   *  of the iterable object <code>elems</code> from the set.
   *
   *  @param elems An iterable object containing the elements to remove from the set.
   *  @return a new set with the elements removed.
   */
  def -- (elems: Iterable[A]): Set[A] = this -- elems.elements

  /** Remove all the elements provided by an iterator
   *  <code>elems</code> from the set.
   *  @param elems An iterator containing the elements to remove from the set.
   *  @return a new set with the elements removed.
   */
  def -- (elems: Iterator[A]): Set[A] =
    (this /: elems) ((s, elem) => s - elem)

  /** <code>excl</code> removes many elements from the set.
   */
  [deprecated] def excl(elems: A*): Set[A] = excl(elems)

  /** This method removes all the elements provided by an iterator
   *  of the iterable object <code>that</code> from the set.
   */
  [deprecated] def excl(that: Iterable[A]): Set[A] =
    that.foldLeft(this)((set, elem) => set - elem)

  /** This method computes an intersection with set <code>that</code>.
   *  It removes all the elements that are not present in <code>that</code>.
   *
   *  @param that the set to intersect with
   */
  def intersect(that: collection.Set[A]): Set[A] = filter(that.contains)

  /** This method is an alias for <code>intersect</code>.
   *  It computes an intersection with set <code>that</code>.
   *  It removes all the elements that are not present in <code>that</code>.
   *
   *  @param that the set to intersect with
   */
   def ** (that: collection.Set[A]): Set[A] = intersect(that)

  /** Returns the set resulting from applying the given function <code>f</code> to each
   *  element of this set.
   *
   *  @param f function to apply to each element.
   *  @return a set containing <code>f(a0), ..., f(an)</code>
   *          if this set contains <code>a0, ..., an</code>.
   */
  override def map[B](f: A => B): Set[B] =
    foldLeft(empty[B])((set: Set[B], elem: A) => set + f(elem))

  /** Applies the given function <code>f</code> to each element of
   *  this set, then forms the union of all results.
   *  @param f function to apply to each element.
   *  @return a set containing all elements in each <code>f(a0), ..., f(an)</code>
   *          if this set contains <code>a0, ..., an</code>.
   */
  override def flatMap[B](f: A => Iterable[B]): Set[B] =
    foldLeft(empty[B])((set: Set[B], elem: A) => set incl f(elem))

  /** Method <code>filter</code> removes all elements from the set for
   *  which the predicate <code>p</code> yields the value <code>false</code>.
   *
   *  @param p The predicate used to filter the set
   */
  override def filter(p: A => Boolean): Set[A] =
    foldLeft(this)((set, elem) => if (p(elem)) set else set - elem)

}