2012-12-20 8 views
13

Utilizzando un ciclo for con una semplice opzione funziona:Perché Option richiede esplicitamente toList inside for loops?

scala> for (lst <- Some(List(1,2,3))) yield lst 
res68: Option[List[Int]] = Some(List(1, 2, 3)) 

Ma loop sul contenuto della facoltà di non fa:

scala> for (lst <- Some(List(1,2,3)); x <- lst) yield x 
<console>:8: error: type mismatch; 
found : List[Int] 
required: Option[?] 
       for (lst <- Some(List(1,2,3)); x <- lst) yield x 
              ^

... a meno che l'opzione è esplicitamente convertito in un elenco:

scala> for (lst <- Some(List(1,2,3)).toList; x <- lst) yield x 
res66: List[Int] = List(1, 2, 3) 

Perché è necessaria la conversione esplicita dell'elenco? È questa la soluzione idiomatica?

risposta

12
for (lst <- Some(List(1,2,3)); x <- lst) yield x 

si traduce per

Some(List(1,2,3)).flatMap(lst => lst.map(x => x)) 

Il metodo flatMap su Option prevede una funzione che restituisce un Option, ma si sta passando una funzione che restituisce un List e non v'è alcuna conversione implicita da List a Option.

Ora, se si converte l'Option a un elenco prima, il metodo di ListflatMap si chiamerà invece, che prevede una funzione che restituisce un List, che è quello che sta passando ad esso.

In questo caso particolare, credo che la soluzione più idiomatica è

Some(List(1,2,3)).flatten.toList 
+0

Che è il motivo per cui 'for (LST <- Alcuni (Lista (1,2,3)) get; x <- Opzione (LST)) yield x' funziona anche. Interessante. – sberry