2010-02-24 11 views
37

¿Cuál es el camino de la Scala de escribir el siguiente código:Match "fallthrough": ¿se ejecuta el mismo código para más de un caso?

int i; 

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

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

    default: foo()   
} 

es decir, ¿Cuál es la forma idiomática de ejecutar el mismo fragmento de código basado en múltiples valores de casos?

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

no parece bastante hacer el truco, ya Scala evalúa el valor partido basado en el primer caso de coincidencia, es decir, si i = 2 el código volveré nada.

¡Gracias por la ayuda!

Respuesta

49

De acuerdo con this conversation no hay caída, pero puede hacer uso de |.

Esto debe hacer el truco:

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

Eliminé '{' y '}' alrededor de 'b' y' c', para aclarar que no son necesarios. –

+0

Gracias, Daniel. No pensé en esto yo mismo. – middus

+0

tan obvio, pero tan fácil de perder – Loki

10

declaraciones de caso pueden incluir realidad guardias lógicas adicionales utilizando un estándar sentencia if. Por lo que podría hacer algo como:

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

Los guardias de adaptación puede ser cualquier función booleana o la composición de funciones, por lo que le da mucha más energía que la sentencia switch estándar en Java.

+0

Tenga en cuenta que si lo prefiere, no hay necesidad de paréntesis que rodeen la condición de guarda en una cláusula 'case ...'. –

3

Si bien no se aplica aquí, para problemas más complejos puede 'descender' en cierto sentido utilizando la función y luego en funciones parciales.

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

Si se trata de clases reales (en lugar de cadenas o enteros), es necesario _: antes de cada clase para convertirlos en un patrón antes de unirse con |.

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! 

¡Obtienes un buen control exhaustivo también! Tenga en cuenta que no se puede desestructurar la clase de caso cuando se usa una coincidencia de patrón alternativa (por ejemplo, case (MateySnoresTooLoud(str) | _: Ok) => no se compilará

Cuestiones relacionadas