2013-05-11 11 views
10

Sto leggendo tramite Scala for the Impatient e mi sono imbattuto in qualcosa che mi ha graffiato la testa.Restituisci il tipo di Scala per/yield

Le seguenti restituisce una stringa:

scala> for (c<-"Hello"; i <- 0 to 1) yield (c+i).toChar 
res68: String = HIeflmlmop 

Ma questo restituisce un vettore:

scala> for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar 
res72: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p) 

Il testo che precede questi due esempi si legge ...

"Quando il corpo del ciclo for inizia con yield, quindi il ciclo costruisce un insieme di valori, uno per ogni iterazione ... Questo tipo di op è chiamato a comprensione. La raccolta generata è compatibile con il primo generatore.

Se la raccolta generato è compatibile con il primo generatore, allora perché non è il secondo esempio restituire un tipo di intervallo, come nell'esempio seguente:

scala> val range = 0 to 1 
range: scala.collection.immutable.Range.Inclusive = Range(0, 1) 

O sto interpretando male tutto ciò che il testo significa "... la raccolta generata è compatibile con il primo generatore".

+0

Date un'occhiata a [questa risposta superiore] (http://stackoverflow.com/a/1716558/406435) per ottenere una migliore visione su come funziona. E [qui] (http: //www.devoxx.com/display/FR13/Martin + Odersky) (a partire da 42:40) Martin Odersky stesso spiega la storia, la motivazione e l'implementazione delle collezioni scala. – senia

risposta

4

per la comprensione viene eseguito su una serie di operazioni map, flatMap e filter.

Quando si utilizza map su un Range, si ottiene un Vector uscita:

scala> 0 to 2 map (x => x * x) 
res12: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 4) 

Questo perché un Range è molto semplice sorta di raccolta, che è essenzialmente solo due tre numeri: un inizio valore, un valore finale e un passo. Se si guarda il risultato della mappatura sopra, è possibile vedere che i valori risultanti non possono essere rappresentati da qualcosa del tipo Range.

0

in questo for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar comprensione, il primo generatore è di tipo scala.collection.immutable.Range.Inclusive il vettore risultato resa è di tipo scala.collection.immutable.IndexedSeq [Int] e se di controllare la classe Gamma: http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Range

mostra Gamma estende/mixin il IndexedSeq. il tipo super IndexedSeq è compatibile con il sottotipo Intervallo.

Se il risultato non può essere rappresentato da un intervallo (come spiegato nella risposta precedente), cercherà "il tipo super" per rappresentare il risultato.

enter image description here