我知道您可以像
那样在列表上进行匹配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 :(得分: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
执行紧凑性操作会很好,但Scala不允许参数化提取器;请参阅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)
的含义相同,这使得语法看起来不错。
答案 1 :(得分:4)
与case head :: tail
匹配使用p1 op p2
形式的中缀操作模式,在进行实际匹配之前将其转换为op(p1, p2)
。 (有关::
)
+
的问题如下:
虽然很容易添加
object + {
def unapply(value: Int): Option[(Int, Int)] = // ...
}
进行匹配的对象,每个值只能提供一个结果。 E.g。
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
是什么。
答案 2 :(得分:1)
Scala中有两个::
s(发音为“cons”)。一个是List
s上的运算符,另一个是类,它表示以头和尾为特征的非空列表。所以head
:: tail
是构造函数模式,与运算符无关。