summaryrefslogblamecommitdiff
path: root/src/library/scala/collection/generic/SetTemplate.scala
blob: ed706ab1bc0ad7a78b8c14b76034515657cd86a0 (plain) (tree)
1
2
3
4
5
6
7
8







                                                                          









                                                                                              

                         
  





                                                                                                 
   

                                                                                                                                                    

                 
                                                                                               








                                                                         

                                                                                          
     
                       
 
                                                                                                    
                                           
     
                       
















                                                                         

                                                                                   


                                            

                                                           








                                                                                   






                                                                            
 
                                                                
    


                                                                   
     
                                               
 
                                                                
    
                                            

                                                                   








                                                                                     
     
                                         
 





                                                                                     
     
                                         

















                                                                      
     
                                                        
                         






                                                    



             





                                                                                          
                                                          
 


 
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2009, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $

package scala.collection.generic

/** A generic template for sets of type A.
 *  To implement a concrete set, you need to provide implementations of the following methods:
 *  (where This is the type of the set in question):
 *
 *   def contains(key: A): Boolean
 *   def elements: Iterator[A]
 *   def +(elem: A): This
 *   def -(elem: A): This
 *
 * If you wish that methods like, take, drop, filter return the same kind of set, you should also
 * override:
 *
 *   def empty: This
 *
 * It is also good idea to override methods foreach and size for efficiency.
 */
trait SetTemplate[A, +This <: SetTemplate[A, This] with Set[A]] extends IterableTemplate[A, This] with Addable[A, This] with Subtractable[A, This] {
self =>

  def empty: This
  override protected[this] def newBuilder: Builder[A, This] = new AddingBuilder[A, This](empty)

  /** Checks if this set contains element <code>elem</code>.
   *
   *  @param elem the element to check for membership.
   *  @return     <code>true</code> iff <code>elem</code> is contained in
   *              this set.
   */
  def contains(elem: A): Boolean

  /** Creates a new set with an additional element, unless the element is already present.
   *  @param elem the element to be added
   */
  def + (elem: A): This

  /** Creates a new set with given element removed from this set, unless the element is not present.
   *  @param elem the element to be removed
   */
  def - (elem: A): This

  /** Checks if this set is empty.
   *
   *  @return <code>true</code> iff there is no element in the set.
   */
  override def isEmpty: Boolean = size == 0

  /** This method allows sets to be interpreted as predicates.
   *  It returns <code>true</code>, iff this set contains element
   *  <code>elem</code>.
   *
   *  @param elem the element to check for membership.
   *  @return     <code>true</code> iff <code>elem</code> is contained in
   *              this set.
   */
  def apply(elem: A): Boolean = contains(elem)

  /** Returns a new set consisting of all elements that are both in the current set
   *  and in the argument set.
   *
   *  @param that the set to intersect with.
   */
  def intersect(that: Set[A]): This = filter(that.contains)

  /** Returns a new set consisting of all elements that are both in the current set
   *  and in the argument set.
   *
   *  @param that the set to intersect with.
   *  @note  same as `intersect`
   */
  def &(that: Set[A]): This = intersect(that)

 /**  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
   *  @deprecated use & instead
   */
  @deprecated def ** (that: Set[A]): This = intersect(that)

  /** The union of this set and the given set <code>that</code>.
   *
   *  @param that the set of elements to add
   *  @return     a set containing the elements of this
   *              set and those of the given set <code>that</code>.
   */
  def union(that: Set[A]): This = this.++(that)

  /** The union of this set and the given set <code>that</code>.
   *
   *  @param that the set of elements to add
   *  @return     a set containing the elements of this
   *              set and those of the given set <code>that</code>.
   *  @note       same as `union`
   */
  def | (that: Set[A]): This = union(that)

  /** The difference of this set and the given set <code>that</code>.
   *
   *  @param that the set of elements to remove
   *  @return     a set containing those elements of this
   *              set that are not also contained in the given set <code>that</code>.
   */
  def diff(that: Set[A]): This = --(that)

  /** The difference of this set and the given set <code>that</code>.
   *
   *  @param that the set of elements to remove
   *  @return     a set containing those elements of this
   *              set that are not also contained in the given set <code>that</code>.
   *  @note       same as `diff`.
   */
  def &~(that: Set[A]): This = diff(that)

  /** Checks if this set is a subset of set <code>that</code>.
   *
   *  @param that another set.
   *  @return     <code>true</code> iff the other set is a superset of
   *              this set.
   *  todo: rename to isSubsetOf
   */
  def subsetOf(that: Set[A]): Boolean = forall(that.contains)

  /** Compares this set with another object and returns true, iff the
   *  other object is also a set which contains the same elements as
   *  this set.
   *
   *  @param that the other object
   *  @note not necessarily run-time type safe.
   *  @return     <code>true</code> iff this set and the other set
   *              contain the same elements.
   */
  override def equals(that: Any): Boolean = that match {
    case other: Set[_] =>
      if (this.size == other.size)
        try { // can we find a safer way to do this?
          subsetOf(other.asInstanceOf[Set[A]])
        } catch {
          case ex: ClassCastException => false
        }
      else false
    case _ =>
      false
  }

  /** Defines the prefix of this object's <code>toString</code> representation.
   */
  override def stringPrefix: String = "Set"

  /** Need to override string, so that it's not the Function1's string that gets mixed in.
   */
  override def toString = super[IterableTemplate].toString
}