2011-07-18 15 views
6

我知道,你可以做配套上列出的方式像匹配与自定义组合/运营商

val list = List(1,2,3) 
list match { 
    case head::tail => head 
    case _ => //whatever 
} 

所以我开始怀疑这是如何工作。如果我理解正确,::仅仅是一个运营商,所以什么是从做这样的事情

4 match { 
    case x + 2 => x //I would expect x=2 here 
} 

如果有一种方式来创建这样的功能,它是如何做阻止我;如果不是,那为什么?

+0

为什么不使用'y-2'(当y = 4时)? –

+0

这更多的是好奇心,所以我没有任何具体的例子,但我想这对于更复杂的类很好。 – Dylan

回答

8

模式匹配采用输入并使用unapply函数进行分解。所以在你的情况下,unapply(4)将不得不返回总和为4的两个数字。然而,有很多对的总和为4,所以该函数不知道该怎么做。

你需要的是2可以以某种方式访问​​unapply函数。存储的2一个特例类将这项工作:

case class Sum(addto: Int) { 
    def unapply(i: Int) = Some(i - addto) 
} 

val Sum2 = Sum(2) 
val Sum2(x) = 5 // x = 3 

(这将是很好能够像做val Sum(2)(y) = 5紧凑性,但斯卡拉不允许参数提取;见here

[编辑:这是一个有点傻,但你实际上可以做以下太:

val `2 +` = Sum(2) 
val `2 +`(y) = 5 // y = 3 

]

编辑:head::tail的工作原理是,有一种方法可以从列表的尾部拆分头部。

关于::+相比,没有什么特别的特殊之处:如果您有预先确定的想法来确定打破数字的方式,则可以使用+。例如,如果你想+表示“劈成两半”,那么你可以这样做:

object + { 
    def unapply(i: Int) = Some(i-i/2, i/2) 
} 

,并用它喜欢:

scala> val a + b = 4 
a: Int = 2 
b: Int = 2 

scala> val c + d = 5 
c: Int = 3 
d: Int = 2 

编辑:最后,this解释说,当模式匹配,A op B意味着与op(A,B)相同的东西,这使得语法看起来不错。

+0

我认为你的编辑为我清理了一些东西,今晚晚些时候我将不得不玩这个概念 – Dylan

+0

@Dylan:我重写了散文,所以希望它现在不会混淆。 – dhg

4

case head :: tail匹配使用它获取执行实际匹配之前转换为op(p1, p2)形式p1 op p2缀操作模式。 (见API::

+的问题如下:

虽然很容易添加一个

object + { 
    def unapply(value: Int): Option[(Int, Int)] = // ... 
} 

对象,它会做匹配,你可能只提供每一个结果值。例如。

object + { 
    def unapply(value: Int): Option[(Int, Int)] = value match { 
    case 0 => Some(0, 0) 
    case 4 => Some(3, 1) 
    case _ => None 
} 

现在这个工程:

0 match { case x + 0 => x } // returns 0 

也是这个

4 match { case x + 1 => x } // returns 3 

但这不会和你不能改变它:

4 match { case x + 2 => x } // does not match 

没问题::,虽然,因为它总是定义什么是head和什么是tail的列表。

+0

为API链接+1,我没有意识到这一点。所以从我从中得到的结果来看,List [_]实际上是::的一个子类,因此是一个case类,这就是为什么你可以这样匹配?因此,如果我想提供某种匹配,比如'“hello”匹配{case head :: tail // h + ello ...',那么我需要从一个String到我自己的专用案例类进行隐式转换? – Dylan

1

在Scala中有两个:: s(发音为“cons”)。一个是List s的运营商,另一个是一个类,它表示一个以头部和尾部为特征的非空列表。所以head :: tail是一个构造函数模式,它与运算符无关。