2011-07-16 9 views
6

Me gustaría convertir un único valor en una colección de múltiples "características", sin utilizar una estructura de datos mutable para recopilar los valores. Me gustaría algo como esto constructo de fantasía que utiliza la coincidencia de patrones, pero no se detiene después primer partido:Forma idiomática de convertir A => Seq [B]

scala> 2 multimatch { 
    case i if i > 0 => "Positive" 
    case i if i < 0 => "Negative" 
    case i if (i % 2 == 0) => "Even" 
    //yadda yadda 
} 
res0: Seq[java.lang.String] = List(Positive, Even) 
+0

Solo se aplica un caso. Necesitas anidarlos para que 2 puedan ser reconocidos como positivos e incluso, ¿o estoy perdiendo el punto aquí? – agilesteel

+0

Sí, estoy describiendo algo similar a la coincidencia de patrones, donde se pueden devolver> 1 coincidencia. –

Respuesta

21

Utilizando el patrón de proxeneta, funciones parciales y parámetros repetidos, esto es lo cerca que puedo conseguir:

class MultiMatcher[A](a: A) { 
    def multiMatch[B](pfs: PartialFunction[A, B]*): Seq[B] = { 
    pfs.map(_.lift(a)).collect{ case Some(v) => v } 
    } 
} 

implicit def toMultiMatcher[A](a:A): MultiMatcher[A] = new MultiMatcher(a) 

2 multiMatch (
    { case i if i > 0 => "Positive" }, 
    { case i if i < 0 => "Negative" }, 
    { case i if i % 2 == 0 => "Even" } 
) 
// returns Seq[java.lang.String] = ArrayBuffer(Positive, Even) 
+0

¡Genial! Deberíamos tener esto, la Scala lib ... – Landei

+0

¿Por qué no 'pfs.flatMap (_. Lift (a))'? –

+0

Las conversiones implícitas ahora son 'opt-in', así que agregue 'import scala.language.implicitConversions' antes de definir la conversión implícita. –

8

En primer lugar, definir sus características como funciones de int a Opción [String]

val pos = (i:Int) => if (i > 0) Some("Positive") else None 
val neg = (i:Int) => if (i < 0) Some("Negative") else None 
val even = (i:Int) => if (i % 2 == 0) Some("Even") else None 

Luego haces una lista de características.

val characteristics = pos::neg::even::Nil 

Y luego utiliza flatmap para obtener una lista de las características que se aplican a un determinado objeto.

scala> characteristics.flatMap(f=>f(2)) 
res6: List[java.lang.String] = List(Positive, Even) 
2

En primer lugar, definir una función MultiMatch de la siguiente manera:

scala> def multimatch[A,B](value : A,ps: (A => Boolean, B)*) = 
    |   for (p <- ps 
    |     if (p._1(value))) yield p._2 
multimatch: [A,B](value: A,ps: ((A) => Boolean, B)*)Seq[B] 

Entonces , aquí vamos:

scala> multimatch(2, 
     |   (((x :Int) => x > 0) -> "POSITIVE"), 
     |   (((x :Int) => x < 0) -> "NEGATIVE"), 
     |   (((x :Int) => x % 2 == 0) -> "EVEN") 
     |  ) 

res4: Seq[java.lang.String] = ArrayBuffer(POSITIVE, EVEN) 

O, menos desordenado:

scala> multimatch(2, 
    |   ((x :Int) => x > 0 , "POSITIVE"), 
    |   ((x :Int) => x < 0, "NEGATIVE"), 
    |   ((x :Int) => x % 2 == 0, "EVEN") 
    |  ) 
res5: Seq[java.lang.String] = ArrayBuffer(POSITIVE, EVEN) 
Cuestiones relacionadas