Ryan Denny
Ryan Denny

Reputation: 139

Beginner for loop in Scala: How do I declare a generic element?

I'm new to Scala and am having trouble with a simple generic for-loop declaration, where one instance of my class, FinSet[T] is "unionized" with my another instance of FinSet[T], other. Here is my current implementation of U (short for Union):

def U(other:FinSet[T]) = {
  var otherList = other.toList
  for(otherElem <- 0 until otherList.length){
    this.+(otherElem)
  }
  this
}

When attempting to compile, it receive this error.

error: type mismatch:
found:   : otherElem.type (with underlying type Int)
required : T
    this.+(otherElem)

This is in class ListSet[T], which is an extension of the abstract class FinSet[T]. Both are shown here:

abstract class FinSet[T] protected () {
 /* returns a list consisting of the set's elements */
  def toList:List[T]

  /* given a value x, it retuns a new set consisting of x
     and all the elemens of this (set)
  */
  def +(x:T):FinSet[T]

  /* given a set other, it returns the union of this and other,
     i.e., a new set consisting of all the elements of this and
     all the elements of other
  */
      def U(other:FinSet[T]):FinSet[T]  

  /* given a set other, it returns the intersection of this and other,
     i.e., a new set consisting of all the elements that occur both
     in this and in other
  */
  def ^(other:FinSet[T]):FinSet[T]

  /* given a set other, it returns the difference of this and other,
     i.e., a new set consisting of all the elements of this that
     do not occur in other
  */
  def \(other:FinSet[T]):FinSet[T]

  /* given a value x, it retuns true if and only if x is an element of this 
  */
  def contains(x: T):Boolean

  /* given a set other, it returns true if and only if this is included
     in other, i.e., iff every element of this is an element of other
  */
  def <=(other:FinSet[T]):Boolean = 
    false // replace this line with your implementation


  override def toString = "{" ++ (toList mkString ", ") ++ "}"

  // overrides the default definition of == (an alias of equals)
  override def equals(other:Any):Boolean = other match {
    // if other is an instance of FinSet[T] then ...
    case o:FinSet[T] => 
      // it is equal to this iff it includes and is included in this
      (this <= o) && (o <= this)
    case _ => false
  }
}

And here, ListSet:

class ListSet[T] private (l: List[T]) extends FinSet[T] {
  def this() = this(Nil)

  // invariant: elems is a list with no repetitions
  //            storing all of the set's elements 
  private val elems = l

  private def add(x:T, l:List[T]):List[T] = l match {
    case Nil => x :: Nil
    case y :: t => if (x == y) l else y :: add(x, t)
  }

  val toList = 
    elems

  def +(x: T) = 
    this.toList.+(x)

  def U(other:FinSet[T]) = {
    var otherList = other.toList
    for(otherElem <- 0 until otherList.length){
      this.+(otherElem)
    }
    this
  }

  def ^(other:FinSet[T]) = 
    this

  def \(other:FinSet[T]) = 
    this

  def contains(x:T) = 
    false
}

Am I missing something obvious here?

Upvotes: 0

Views: 236

Answers (1)

Shadowlands
Shadowlands

Reputation: 15074

In your for loop you are assigning Ints to otherElem (x until y produces a Range[Int], which effectively gives you an iteration over the Ints from x up to y), not members of otherList. What you want is something like:

  def U(other:FinSet[T]) = {
    for(otherElem <- other.toList){
      this.+(otherElem)
    }
    this
  }

EDIT:

Curious, given your definitions of FinSet and ListSet (which I didn't see until after giving my initial answer), you ought to have some other issues with the above code (+ returns a List, not a FinSet, and you don't capture the result of using + anywhere, so your final return value of this ought to just return the original value of the set - unless you are not using the standard Scala immutable List class? If not, which class are you using here?). If you are using the standard Scala immutable List class, then here is an alternative to consider:

def U(other:FinSet[T]) = new ListSet((this.toList ++ other.toList).distinct)

In general, it looks a bit like you are going to some trouble to produce mutable versions of the data structures you are interested in. I strongly encourage you to look into immutable data structures and how to work with them - they are much nicer and safer to work with once you understand the principles.

Upvotes: 1

Related Questions