Почему у Iterator есть метод contains, но Iterable в Scala 2.8?

Я хотел бы назвать 'contains' на моих Iterables: -)

Ответы

Ответ 1

Причина Iterable не имеет метода contains, потому что способ, которым он определен, может иметь прямые последствия для дисперсии. В принципе, существуют две сигнатуры типа, которые имеют для этого смысл:

def contains(v: Any): Boolean
def contains(v: A): Boolean

Второе определение повышает безопасность типов. Тем не менее, A, который является параметром типа коллекции, появляется в контравариантном положении, что заставляет коллекцию быть инвариантной. Его можно определить следующим образом:

def contains[B >: A](v: B): Boolean

но это не улучшило бы первую подпись, используя Any.

В результате этого вы увидите, что immutable.Seq является ко-вариантом и использует первую подпись, тогда как immutable.Set является инвариантным и использует вторую подпись.

Ответ 2

Я не знаю, почему contains не определено на Iterable или TraversableOnce, но вы можете легко определить его сами:

class TraversableWithContains[A](underlying: TraversableOnce[A]) {
  def contains(v: Any): Boolean =
    underlying.exists(_ == v)
}
implicit def addContains[A](i: Iterable[A]) = new TraversableWithContains(i)

и использовать его так, как если бы он был определен в Iterable:

val iterable: Iterable[Int] = 1 to 4
assert(iterable.contains(3))
assert(!iterable.contains(5))