2009-11-25 7 views
58

Wenn ich so etwas wie ein List[Option[A]] haben und ich möchte diese in eine List[A] konvertieren, ist der normale Weg flatMap zu verwenden:Gibt es eine Scala-Identitätsfunktion?

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) 

Jetzt o => o ist nur eine Identitätsfunktion. Ich hätte gedacht, es würde irgendwie zu tun:

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

Allerdings kann ich das nicht bekommen zu arbeiten, wie Sie keine object generify können. Ich habe ein paar Dinge vergeblich versucht; Hat jemand so etwas zum arbeiten?

+2

Ich würde denken, dass '{_}' gleichsetzen sollte '{x => x}' genau wie '{_ + 3}' entspricht '{x => x + 3}'. Kann jemand kommentieren, warum es nicht so ist? –

Antwort

52

Es gibt eine Identität function in Predef.

l flatMap identity[Option[String]] 

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

A für expresion ist schöner, nehme ich an:

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

Edit:

Ich habe versucht, herauszufinden, warum die der Typparameter (Option [String]) benötigt wird. Das Problem scheint die Typumwandlung von Option [T] zu Iterable [T] zu sein.

Wenn Sie die Identitätsfunktion definieren als:

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

der Typparameter verzichtet werden kann.

+0

Wie kommt es, dass der Typinfinfer die Typen selbst nicht herausfinden kann? Warum funktioniert 'l.flatMap (identity): List [String]' nicht? –

+0

Ich dachte, der Inferenz könnte das herausfinden. Ich habe keine Ahnung. Ich werde eine Frage hinzufügen. :-) –

+1

@oxbow_lakes - Siehe bearbeiten. Es bezieht sich auf implizite Typkonvertierungen. –

21

FWIW, auf Scala 2.8 rufen Sie einfach flatten darauf an. Thomas hat es meist für Scala 2.7 abgedeckt. Er verpasste nur eine Alternative Art und Weise, dass die Identität der Verwendung:

l.flatMap[String](identity) 

Es wird nicht mit Operator Notation arbeiten, aber (es scheint Notation Bediener nicht Typparameter akzeptieren, was gut ist zu wissen).

Sie können auch Aufruf flatten auf Scala 2.7 (auf einem List zumindest), aber es wird nicht in der Lage sein, etwas ohne eine Art zu tun. Dies funktioniert jedoch:

l.flatten[String] 
2

Sie könnten nur die Art Rückschließer ein wenig Hilfe geben:

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)