Scala provides two variations on “filter” which at first glance appear similar:
List("a", "b", "c").filter(_ == "b")
res3: List[String] = List(b)
Comparatively, “withFilter” takes the same syntax, but returns an object:
List("a", "b", "c").withFilter(_ == "b")
res4: scala.collection.generic.FilterMonadic[String,List[String]] =
scala.collection.TraversableLike$WithFilter@32ae8f27
The difference between these two is that “withFilter” doesn’t do any work, until values are pulled from the collection. In this sense, it is exactly like a view, although it is a single function implementation vs. all the other features views would add.
Once you’ve applied “withFilter, you’re pretty committed – the resulting thing doesn’t let you switch back to filter, punishing you with an ugly error:
scala> List("a", "b", "c").withFilter(_ == "b").filter(x => true)
:12: error: value filter is not a member of
scala.collection.generic.FilterMonadic[String,List[String]]
List("a", "b", "c").withFilter(_ == "b").filter(x => true)
On the other hand, you can apply withFilter again:
List("a", "b", "c")
.withFilter(_ == "b")
.withFilter(x => true)
res7: scala.collection.generic.FilterMonadic[String,List[String]] =
scala.collection.TraversableLike$WithFilter@144e36ae
To realize the resulting collection, you need to do whatever your final operation is (e.g. map), to get the results back:
List("a", "b", "c")
.withFilter(_ == "b")
.map(x => x)
res9: List[String] = List(b)
And there, you have the expected result.