2010-02-24 6 views
37

Was die Scala Weg ist, den folgenden Code zu schreiben:Match "FallThrough": Ausführung des gleichen Code für mehr als einen Fall?

int i; 

switch(i) { 
    case 1: 
     a(); 
     break; 

    case 2: 
    case 15: 
     b(); 
     c(); 
     break; 

    default: foo()   
} 

D.h. Was ist die idiomatische Art, denselben Code basierend auf mehreren Case-Werten auszuführen?

i match { 
    case 1 => a  
    case 2 => 
    case 15 => { b 
       c } 
    case _ => foo   
} 

nicht ganz scheinen den Trick, da Scala den Übereinstimmungswert wertet auf dem ersten Anpassungs Fall basiert, das heißt, wenn i = 2 wird der Code nichts zurück.

Vielen Dank für Ihre Hilfe!

Antwort

49

Gemäß this conversation gibt es keinen Fall durch, aber Sie können | verwenden.

Dies sollte den Trick:

i match { 
    case 1 => a  
    case 2 | 15 => b 
       c 
    case _ => foo   
} 
+3

Ich habe '{' und '}' um 'b' und' c' entfernt, um deutlich zu machen, dass sie unnötig sind. –

+0

Danke, Daniel, habe nicht selbst darüber nachgedacht – middus

+0

so offensichtlich, aber so leicht zu übersehen – Loki

10

Fall-Anweisungen können tatsächlich zusätzliche Logik Wachen eine Standard-if-Anweisung verwenden. So könnte man so etwas wie:

i match { 
    case x if x == 1 => a 
    case x if (x == 2 | x == 15) => b; c; 
    case _ => foo 
} 

Die passenden Wachen jede Boolesche Funktion oder die Zusammensetzung von Funktionen sein können, so dass es ihm gibt viel mehr Leistung als die Standard-Switch-Anweisung in Java.

+0

Beachten Sie, dass, wenn Sie bevorzugen, es keine Notwendigkeit für Klammern gibt, die die Schutzbedingung in einer 'case ...' Klausel umgeben. –

3

Obwohl dies hier nicht anwendbar ist, können Sie bei komplexeren Problemen in gewissem Sinne mit der Und-Funktion bei Teilfunktionen "durchgehen".

def do_function_a() { println("a"); } 
def do_function_b() { println("b"); } 
val run_function:PartialFunction[String, String] = { 
     case "a" => do_function_a(); "b" 
     case "b" => do_function_b(); "c" 
} 

(run_function andThen run_function)("a") // a\nb 
1

Wenn Sie mit den tatsächlichen Klassen handelt (statt Strings oder Ints), müssen Sie _: vor jeder Klasse sie in ein Muster zu machen, bevor sie mit | verbinden.

sealed trait ShipCondition 
case class ShipOnFire() extends ShipCondition 
case class FoodSucks() extends ShipCondition 
case class MateySnoresTooLoud() extends ShipCondition 
case class Ok() extends ShipCondition 

val condition = ShipOnFire() 

def checkCondition(cond: ShipCondition): Unit = { 
    cond match { 
    case c @ (_: ShipOnFire | _: FoodSucks) => println("Abandon Ship!") // can also use `c` for something. It has the type ShipCondition 
    case (_: MateySnoresTooLoud | _: Ok) => println("Deal with it!") 
    } 
} 

checkCondition(condition) // Abandon Ship! 

Sie erhalten auch schön erschöpfende Prüfung! Beachten Sie, dass Sie bei der Verwendung alternativer Mustervergleiche keine Fallklassendestrukturierung durchführen können (z. B. case (MateySnoresTooLoud(str) | _: Ok) => wird nicht kompiliert.

Verwandte Themen