2011-07-16 75 views
6

我想将单个值转换为多个“特性”的集合,而不使用可变数据结构来收集值。我想类似的东西,它使用模式匹配这个奇幻的概念,但是第一场比赛后没有停止: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

只有一种情况可以匹配。你需要将它们嵌套在一起,这样2可以被认为是正面甚至是正确的,或者我在这里忽略了这一点? – agilesteel

+0

是的,我正在描述类似于模式匹配的东西,其中可以返回> 1个匹配。 –

回答

21

使用皮条客模式,部分功能和重复参数,这是我近可以得到:

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

酷!我们应该有这个Scala库... – Landei

+0

为什么不用'pfs.flatMap(_。lift(a))'? –

+0

隐式转换现在是“选择加入”,所以在定义隐式转换之前添加'import scala.language.implicitConversions'。 –

8

首先,你从int到选项定义特征函数[字符串]

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 

然后你列出一些特征。

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

然后您使用flatmap来获取适用于某个对象的那些特征的列表。

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

首先,定义一个multimatch功能如下:

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] 

然后,这里我们去:

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) 

或者更少混乱:

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) 
相关问题