Collection type generated by for with yield
Asked Answered
I

2

22

When I evaluate a for in Scala, I get an immutable IndexedSeq (a collection with array-like performance characteristics, such as efficient random access):

scala> val s = for (i <- 0 to 9) yield math.random + i
s: scala.collection.immutable.IndexedSeq[Double] = Vector(0.6127056766832756, 1.7137598183155291, ...

Does a for with a yield always return an IndexedSeq, or can it also return some other type of collection class (a LinearSeq, for example)? If it can also return something else, then what determines the return type, and how can I influence it?

I'm using Scala 2.8.0.RC3.

Inshore answered 1/6, 2010 at 7:18 Comment(1)
Have a look at #1052976 and https://mcmap.net/q/275462/-scala-2-8-canbuildfromAgathaagathe
I
19

Thanks michael.kebe for your comment.

This explains how for is translated to operations with map, flatMap, filter and foreach. So my example:

val s = for (i <- 0 to 9) yield math.random + i

is translated to something like this (I'm not sure if it's translated to map or flatMap in this case):

val s = (0 to 9) map { math.random + _ }

The result type of operations like map on collections depends on the collection you call it on. The type of 0 to 9 is a Range.Inclusive:

scala> val d = 0 to 9
d: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

The result of the map operation on that is an IndexedSeq (because of the builder stuff inside the collections library).

So, to answer my question: the result of a for (...) yield ... depends on what type is inside the parantheses. If I want a List as the result, I could do this:

scala> val s = for (i <- List.range(0, 9)) yield math.random + i
s: List[Double] = List(0.05778968639862214, 1.6758775042995566, ...
Inshore answered 1/6, 2010 at 8:17 Comment(2)
It's translated to map in your case. If you have a for comprehension with two generators, this is translated into a flatMap/map combination. So for (i <- 0 until 9; j <- 0 until i) yield(ij) is translated to (0 until 9).flatMap{case i => (0 until i).map{case j=> ij}}Confine
"depends on what type is inside the parantheses", more precise its the first right side parameter which determines the type.Fret
C
6

You can always transform a range to a list using toList:

> val s = for (i <- (0 to 9).toList) yield math.random + i
> s  : List[Double]
Contredanse answered 29/4, 2013 at 22:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.