1
votes

I'm completely new to Scala so bear with me please! I am going through some Scala exercises and one of them is to create a list of odd numbers from 1 to 20. This is pretty straight forward but I'm a bit confused about the return type of the filter method on a range.

I have the following block:

val lst2 = (1 to 20).filter(_ % 2 != 0)
println(lst2)

The output of this is:

Vector(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)

However when I explicitly set the type of lst2 to Vector[Int] like the following:

val lst2: Vector[Int] = (1 to 20).filter(_ % 2 != 0)
println(lst2)

I get the this:

16: error: type mismatch;

found : scala.collection.immutable.IndexedSeq[Int]

required: Vector[Int] val lst2: Vector[Int] = (1 to 20).filter(_ % 2 != 0) ^ one error found

So what's gonig on here? Is the println method just not giving me the correct type? How do I get the filter method to return a Vector?

1

1 Answers

5
votes

The only guarantee that is provided by filter of Range is that it returns a collection.immutable.IndexedSeq[A], so this compiles:

val lst2: collection.immutable.IndexedSeq[Int] = (1 to 20).filter(_ % 2 == 1)

At runtime, lst2 just happens to be a Vector[Int], but this is not guaranteed by the interface, so the authors of the filter method effectively reserve the right to change the concrete implementation to another IndexedSeq whenever they like. The type Vector is an implementation detail you shouldn't rely on.

The reason why it's printed as Vector(...) is that it depends on the implementation of toString of a concrete instance that is present at runtime, not on the statically know type (dynamic dispatch).

If you really want something with type Vector, just append .toVector:

val lst2: Vector[Int] = (0 to 20).filter(_ % 2 == 1).toVector