2009-11-25 6 views
58

Se ho qualcosa di simile a un List[Option[A]] e voglio convertire questo in un List[A], il modo standard è quello di utilizzare flatMap:Esiste una funzione di scala identità?

scala> val l = List(Some("Hello"), None, Some("World")) 
l: List[Option[java.lang.String]] = List(Some(Hello), None, Some(World)) 

scala> l.flatMap(o => o) 
res0: List[java.lang.String] = List(Hello, World) 

Ora o => o è solo una funzione identità. Avrei pensato che ci sarebbe un modo per farlo:

l.flatMap(Identity) //return a List[String] 

Tuttavia, non posso ottenere questo a lavorare come non si può generify un object. Ho provato alcune cose inutilmente; qualcuno ha qualcosa di simile a funzionare?

+2

mi piacerebbe pensare che '{} _' dovrebbe equivalere a '{x => x}' proprio come '{_ + 3}' equivale a '{x => x + 3}'. Qualcuno può commentare perché non è così? –

risposta

52

C'è un'identità function in Predef.

l flatMap identity[Option[String]] 

> List[String] = List(Hello, World) 

A per expresion è più bello, suppongo:

for(x <- l; y <- x) yield y 

Edit:

ho cercato di capire il motivo per cui è necessario il parametro type (Opzione [String]). Il problema sembra essere il tipo di conversione da Opzione [T] a Iterable [T].

Se si definisce la funzione identità:

l.flatMap(x => Option.option2Iterable(identity(x))) 

il parametro di tipo possono essere omessi.

+0

Come mai il tipo di iniziatore non riesce a capire i tipi stessi? Perché 'l.flatMap (identity): List [String]' funziona? –

+0

Pensavo che l'infernerore potesse capirlo. Non ne ho idea. Aggiungerò una domanda :-) –

+1

@oxbow_lakes - Vedi modifica. È correlato a conversioni di tipo implicito. –

21

FWIW, su Scala 2.8 è sufficiente chiamare flatten su di esso. Thomas è coperto principalmente per Scala 2.7. Gli mancava solo un modo alternativo di usare tale identità:

l.flatMap[String](identity) 

Non funzionerà con la notazione dell'operatore, però (sembra la notazione operatore non accetta parametri di tipo, che è bene sapere).

È possibile anche chiamata flatten su Scala 2.7 (su un List, almeno), ma non sarà in grado di fare nulla senza un tipo. Tuttavia, questo funziona:

l.flatten[String] 
2

si può solo dare il tipo inferencer un piccolo aiuto:

scala> val l = List(Some("Hello"), None, Some("World")) 
l: List[Option[java.lang.String]] = List(Some(Hello), None, Some(World)) 

scala> l.flatten[String] 
res0: List[String] = List(Hello, World)