Scala: filter vs withFilter

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]] = 

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)
<console>:12: error: value filter is not a member of 
       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]] = 

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.

If you want a good book on Scala, take a look at Programming Scala (I'm currently reading through this).

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *