2017-01-13 1 views
0

Wie kann man das Folgende umschreiben, um es mehr "Scala Weg" zu machen oder nur eine Übereinstimmung zu verwenden?Scala: Mustervergleich mit Option [Foo] und Parameter von Foo

case class Foo(bar: Any) 
val fooOpt = Some(Foo("bar as String")) 

def isValid(p: Any) = p match { 
    case _ @ (_: String | _: Int) => true 
    case _ => false 
} 

//Is it possible to check for the type of bar directly in this if statement? 
fooOpt match { 
    case Some(f) if isValid(f.bar) => doSomething 
    case _ => doSomethingElse 
} 

Eine Alternative wäre die Verwendung des isInstanceOf.

fooOpt match { 
    case Some(f) if f.bar.isInstanceOf[String] => doSomething 
    case Some(f) if f.bar.isInstanceOf[Int] => doSomething //could also rewrite to use just one case 
    case _ => doSomethingElse 
} 

Gibt es einen anderen Weg?

Antwort

1

Dies alles in einem großen Muster Spiel getan werden kann:

fooOpt match { 
    case Some(Foo(_: Int | _: String)) => doSomething 
    case _ => doSomethingElse 
} 

Wenn Sie die Int oder String heraus erhalten möchten, teilen Sie nur, dass case:

fooOpt match { 
    case Some(Foo(i: Int)) => doSomething 
    case Some(Foo(s: String)) => doSomething 
    case _ => doSomethingElse 
} 
+0

Cheers könnte umschreiben zu verwenden! Macht perfekt Sinn. Hatte das Gefühl, dass es eine einfache und einfache Lösung gab! Danke – Bruno

+0

BTW, wenn Foo mehrere Params hatte, wie würden Sie den "Balken" wählen, ohne sie alle zu beschreiben? – Bruno

+0

@Bruno Verwenden Sie einfach Unterstreichungsmuster für die anderen Parameter.So etwas wie 'Some (Foo (i: Int, _, _))' du fügst zwei weitere Parameter zu 'Foo' hinzu. – Alec

1

Gibt es andere Weg?

Obwohl die Lösung mit einem großen pattem Spiel funktioniert (und kann verwendet werden, wenn Sie wirklich nicht bar zu etwas spezifischer als Any ändern können), ist es nicht ein richtiger ‚Scala Weg‘ mit diesen Situationen umzugehen im Allgemeinen, wenn Sie die Kontrolle über Foo haben.

wäre eine bessere Art und Weise Foo generic zu machen sein:

case class Foo[T](bar: T) 

und hat entweder ein allgemeines doSomething, wenn es mit einer bestimmten T arbeiten kann:

def doSomething[T](foo: Foo[T]): SomeType = ??? 

oder hat verschiedene Versionen es für verschiedene mögliche T hast du, wenn es auf sie anders reagieren sollte:

def doSomethingWithString(foo: Foo[String]): SomeType = ??? 
def doSomethingWithInt(foo: Foo[Int]): SomeType = ??? 

Dann können Sie es wie folgt aus:

val fooOpt = Some(Foo("bar as String")) 
fooOpt.map(doSomething).orElse(doSomethingElse) 

oder so:

val fooOptString = Some(Foo("bar as String")) 
fooOptString.map(doSomethingWithString).orElse(doSomethingElse) 

val fooOptInt = Some(Foo(1)) 
fooOptInt.map(doSomethingWithInt).orElse(doSomethingElse) 

in diesem Fall Compiler prüft Typen für Sie also, die Beantwortung zu:

Ist es möglich direkt nach der Art der Bar zu suchen?

Und in vielen Situationen können Sie sich auch alle mit Mustererkennung vermeiden, Methoden wie map verwenden, orElse usw. mit der richtigen Eingabe. Dies könnte eine Antwort auf dieses:

auch nur einen Fall

Verwandte Themen