Is there a built-in more elegant way of filtering-and-mapping a collection by element type?
scala, scala-collections, types
Solution
The Scala syntax sugar for `isInstanceOf` / `asInstanceOf` is pattern matching:
as flatMap { case x: String => Some(x); case _ => None }
Because that uses `flatMap`, it should usually return the same collection you had to begin with.
On Scala 2.8, there's an experimental function that does that kind of pattern, defined inside the object PartialFunction. So, on Scala 2.8 you can do:
as flatMap (PartialFunction.condOpt(_ : Any) { case x: String => x })
Which looks bigger mostly because I did not import that function first. But, then again, on Scala 2.8 there's a more direct way to do it:
as collect { case x: String => x }
Problem
If I want to narrow, say, an `Iterable[A]` for all elements of a particular type (e.g. `String`) I can do: ``` as filter { _.isInstanceOf[String] } ``` However, it's obviously desirable to use this as an `Iterable[String]` which can be done via a `map`: ``` as filter { _.isInstanceOf[String] } map { _.asInstanceOf[String] } ``` Which is pretty ugly. Of course I could use `flatMap` instead: ``` as flatMap[String] { a => if (a.isInstanceOf[String]) Some(a.asInstanceOf[String]) else None } ``` But I'm not sure that this is any more readable! I have written a function, `narrow`, which can be used via `implicit` conversions: ``` as.narrow(classOf[String]) ``` But I was wondering if there was a better built-in mechanism which I have overlooked. Particularly as it would be nice to be able to narrow a `List[A]` to a `List[String]`, rather than to an `Iterable[String]` as it will be with my function.