2015-04-11 8 views

Antwort

18

Es gibt zwei wichtige Unterschiede. Zunächst wird Option ein None zurück, wenn ihr Argument ist null:

scala> val x: Option[String] = Some(null) 
x: Option[String] = Some(null) 

scala> val y: Option[String] = Option(null) 
y: Option[String] = None 

Dies kann nützlich sein, aber es ist nicht immer das, was Sie wollen, und (was genauso wichtig ist) schlägt vor, dass es eine vernünftige Chance, dass das Argument kann in einigen Fällen null sein, was irreführend sein kann.

Some ist besser geeignet für Fälle, in denen Sie einen Option um einen Wert, den Sie wissen, nicht null ist. Leider ist der zweite Unterschied, dass der Rückgabetyp von Some(foo) ist Some[Whatever], nicht Option[Whatever], die wirklich in einigen Situationen unbequem sein kann, in denen Some abgeleitet bedeutet, dass Sie Typfehler erhalten, wenn Sie versuchen, None oder Option in bestimmten Positionen später zu verwenden. In diesen Fällen müssen Sie Some(foo): Option[Whatever] verwenden, was ziemlich unangenehm ist.

Angenommen, wir haben eine Liste von Strings, die (wir hoffen) ganze Zahlen darstellen, und wir wollen sie analysieren und summieren. Wir wollen eine None, wenn es einen Parsing-Fehler gibt und eine Some(total) andernfalls. Im Folgenden ist eine ziemlich vernünftige Möglichkeit, dies in einem einzigen Durchquerung mit der Standardbibliothek zu tun:

List("1", "2", "3").foldLeft(Some(0)) { 
    case (acc, item) => for { 
    t <- acc 
    n <- util.Try(item.toInt).toOption 
    } yield t + n 
} 

Abgesehen davon, dass dies nicht funktioniert-wir bekommen einen Typfehler:

<console>:10: error: type mismatch; 
found : Option[Int] 
required: Some[Int] 
        t <- acc 
        ^

Wir beheben dies durch Schreiben .foldLeft(Some(0): Option[Int]), aber hugh.

Dies ist kein Problem in Ihrem speziellen Beispiel, da der Rückgabetyp explizit Option[Int] ist, so dass Sie sich keine Gedanken über Typinferenz machen müssen. In diesem Fall ist Some(a) die richtige Wahl.

Als Randbemerkung, Scalaz bietet some und none Konstrukteuren, die Sie Typinferenz Problem und laut Lösungen wie Some(foo): Option[Whatever] vermeiden helfen:

scala> import scalaz._, Scalaz._ 
import scalaz._ 
import Scalaz._ 

scala> some(10) 
res0: Option[Int] = Some(10) 

scala> none[Int] 
res1: Option[Int] = None 

Beiden Rückgabetypen sind Option, die Folgerung viel einfacher macht Art. Sie können diese sich trivialer definieren, wenn Sie Scalaz nicht verwenden möchten:

scala> def some[A](a: A): Option[A] = Some(a) 
some: [A](a: A)Option[A] 

scala> def none[A]: Option[A] = None 
none: [A]=> Option[A] 

Wenn Sie diese anstelle von Some verwenden und None Sie haben nie über eine unangemessen bestimmte Art wird gefolgert zu kümmern.

Zusammenfassend: Verwenden Sie Option(foo) nur in Situationen, in denen das Argument Null sein kann (was idealerweise nur für Dinge wie Interoperabilität mit Java sein sollte).Verwenden Sie Some(foo) in Fällen, in denen der Wert explizit als Option eingegeben wurde. Wenn der abgeleitete Typ Some[Whatever] lautet, fügen Sie eine Annotation : Option[Whatever] hinzu oder verwenden Sie etwas wie Scalaz some.

0

Für mich ist es nur eine Frage des gesunden Menschenverstandes. Natürlich können Sie sich den Fall vorstellen, wo Sie etwas genau vom Typ Some and None erwarten dürfen. Aber normalerweise sieht der zweite Weg viel natürlicher aus: der Rückgabetyp ist Option und die tatsächliche Implementierung ist entweder Some (x) oder None. Technisch von source code, Option (x) nennt apply() Methode eines Begleitobjekt:

object Option { 
    import scala.language.implicitConversions 
    implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList 
    def apply[A](x: A): Option[A] = if (x == null) None else Some(x) 
    def empty[A] : Option[A] = None 
} 

und einige (a) ruft apply() Methode auf Fall-Klasse ..

final case class Some[+A](x: A) extends Option[A] { 
    def isEmpty = false 
    def get = x 
} 

Alle anderen Methoden sind die gleichen . Der Anwendungsfall mit null Objekten ist in der Travis Brown Antwort recht gut erklärt.

+2

Es gibt Unterschiede in ihrem Verhalten - versuchen Sie einfach 'Some [String] (null)' und 'Option [String] (null)'. –

+0

Sie haben völlig Recht mit ihrer Initialisierung und Sie haben diesen Benutzerfall in Ihrer Antwort ganz klar erklärt! Ich werde meine Antwort bearbeiten, um genau zu sein. – ipoteka

Verwandte Themen