2010-06-01 8 views
20

Quando ho valutare un for in Scala, ottengo una immutabile IndexedSeq (un insieme con caratteristiche array come prestazioni, come l'accesso casuale efficiente):tipo Collection generato da per con resa

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

Esiste una for con un yield restituisce sempre un IndexedSeq oppure può anche restituire un altro tipo di classe di raccolta (ad esempio LinearSeq)? Se può anche restituire qualcos'altro, allora cosa determina il tipo di ritorno e come posso influenzarlo?

Sto usando Scala 2.8.0.RC3.

+3

Dai un'occhiata alla http://stackoverflow.com/questions/1052476/can-someone-explain-scalas-yield/1059501 # 1059501 e http://stackoverflow.com/questions/1721356/scala-2-8-canbuildfrom –

risposta

18

Grazie michael.kebe per il tuo commento.

This spiega come for si traduce per le operazioni con map, flatMap, filter e foreach. Quindi il mio esempio:

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

è tradotto in qualcosa di simile (non sono sicuro se è tradotto in map o flatMap in questo caso):

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

Il tipo di risultato di operazioni come map su le raccolte dipendono dalla collezione su cui la chiamate. Il tipo di 0 to 9 è un 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) 

Il risultato dell'operazione map su che è un IndexedSeq (a causa della roba costruttore all'interno della libreria collezioni).

Quindi, per rispondere alla mia domanda: il risultato di un for (...) yield ... dipende da quale tipo è all'interno delle parate. Se voglio un List come risultato, avrei potuto fare questo:

scala> val s = for (i <- List.range(0, 9)) yield math.random + i 
s: List[Double] = List(0.05778968639862214, 1.6758775042995566, ... 
+2

È tradotto in mappa nel tuo caso. Se hai una comprensione per due generatori, questo è tradotto in una combinazione di mappa/mappa. Quindi per (i <- 0 fino a 9; j <- 0 fino a i) yield (i * j) è tradotto in (0 fino a 9) .flatMap {case i => (0 fino a i) .map {case j => i * j}} –

+0

"dipende da quale tipo è all'interno delle parate", più preciso è il primo parametro sul lato destro che determina il tipo. –

5

si può sempre trasformare un intervallo per un elenco utilizzando toList:

> val s = for (i <- (0 to 9).toList) yield math.random + i 
> s : List[Double]