Scala: Filter Behavior on Iterator vs. List
$ scala
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_79).
Type in expressions to have them evaluated.
Type :help for more information.
scala> Iterator(2,4,6)
res0: Iterator[Int] = non-empty iterator
scala> res0.filter
filter filterNot
scala> res0.filter
def filter(p: A => Boolean): Iterator[A]
// Given this filter definition, I would expect the following expression (1) to work:
scala> Iterator(2,4,6).filter(Set(1,2,3).contains).toSet
res1: scala.collection.immutable.Set[Int] = Set(2)
// Question # 1: How does the following expression (2) work? Where does he get his output from A => Boolean
? I wanted to ask where does the bulin come from?
scala> Iterator(2,4,6).filter(Set(1,2,3)).toSet
res2: scala.collection.immutable.Set[Int] = Set(2)
// Question # 2 : Which one is the best expression (1) vs (2) and why?
// Tried the same on List and I expected it to work.
scala> List(2,4,6).filter(List(1,2,3).contains)
res3: List[Int] = List(2)
// Question # 3: Why doesn't this work when it magically worked for an Iterator?
scala> List(2,4,6).filter(List(1,2,3))
<console>:8: error: type mismatch;
found : Int(1)
required: Boolean
List(2,4,6).filter(List(1,2,3))
source to share
Question # 1: How does the following expression (2) work? Where does it get the inference A => Boolean? I wanted to ask where does the bulin come from?
Set[A] extends (A) => Boolean
, so it Set(1, 2, 3)
is a function A => Boolean
. We can see easily as it has an apply method that checks if an element is contained in Set
.
scala> Set(1, 2, 3)(2)
res22: Boolean = true
Question # 2: Which one is the best expression (1) vs (2) and why? Tried the same on List and I expected it to work.
Which one is better is more of a question - functionally they are exactly the same. For those familiar with it Set
, it should be clear that either does (they are both equivalent contains
). It can be said that the use Set(1, 2, 3).contains
makes it more obvious what it is doing. A List
has a method of application, but not the same as Set
. List#apply
- Int => A
- a method for retrieving an item from an index List
by index. Therefore, for lists, you should use contains
.
Question # 3: Why doesn't this work when it magically works for an Iterator?
This is really the same as # 2 . List(1, 2, 3).apply
no Int => Boolean
, it is Int => Int
.
source to share
Answer # 1
The reason filter(Set(1,2,3))
is that it Set
has a method apply
that shadows contains
:
class Set[T] {
def apply(elem: T): Boolean
}
Answer # 2
They are identical.
Answer # 3
That's why it List(2,4,6).filter(List(1,2,3))
doesn't work. If you tried it List(2,4,6).filter(Set(1,2,3))
, it would work. The list is used to access the position in the list:
class List[T] {
def apply(n: Int): Int
}
source to share