Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a Range transformed to a Vector after map operation?

Following Scala courses on Coursera, Martin Odersky showed an example code which is:

1 to 5 map ( i => i*i )

And he said the Range gets transformed to a Vector because they share the same interface (IndexedSeq) and the result could not be represented as a Range (it was more clear in its example since he generated a pair which is not representable as a Range).

I'm not sure to understand because I think he said previously that in a for expression the 1st generator will determine the kind of element that will be yielded, and it seems not always true, at least for Range.

And I'm not sure to understand why the output is Vector, because Vector may not be the only other one implementation that can represent the result computed above.

Can someone help me understand this part please?

like image 254
Sebastien Lorber Avatar asked Oct 29 '12 22:10

Sebastien Lorber


2 Answers

map secretly takes a CanBuildFrom as an implicit argument. Its job is to produce a new collection given the one you've already got (and the type of the contents). Since Range can't contain arbitrary stuff--not even arbitrary integers--there is no CanBuildFrom that produces a Range. The most specific supertype of Range that does have a CanBuildFrom is IndexedSeq. The collection that is actually built by this is a Vector.

like image 119
Rex Kerr Avatar answered Nov 11 '22 17:11

Rex Kerr


As I'm sure Martin also explained, for comprehensions correspond to (are translated into) chained invocations of the map and flatMap methods (and foreach if you don't use yield).

The reason why it generally results in a value of the type of the first generator is that map and flatMap generally return the same type as their receiver (map on a List returns a List, etc.).

Now the problem with Ranges is that they cannot represent things that are not regular sequences of integers. As a consequence, the return type of map and flatMap as defined for Range cannot be Range. The next best match is Vector, the prototypical implementation of an indexed sequence.

(If you look at the source code or even the Scala doc page I linked to, you will see that it is a little more complicated that just the return type, but conceptually, that is the reason. Edit: ...and now Rex Kerr just dropped the CanBuildFrom bomb.)

like image 24
Philippe Avatar answered Nov 11 '22 17:11

Philippe