与自定义组合/运算符匹配

Dyl*_*lan 6 scala pattern-matching

我知道你可以用类似的方式在列表上进行匹配

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

所以我开始想知道它是如何工作的.如果我理解正确,::只是一个操作员,那么阻止我做某些事情的是什么

4 match {
  case x + 2 => x //I would expect x=2 here
}
Run Code Online (Sandbox Code Playgroud)

如果有办法创建这种功能,它是如何完成的; 如果没有,那么为什么呢?

dhg*_*dhg 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
Run Code Online (Sandbox Code Playgroud)

(能够做一些类似于val Sum(2)(y) = 5紧凑的事情会很好,但Scala不允许参数化提取器;请参阅此处.)

[编辑:这有点傻,但你实际上也可以做以下事情:

val `2 +` = Sum(2)
val `2 +`(y) = 5  // y = 3
Run Code Online (Sandbox Code Playgroud)

]

编辑:head::tail事情的原因是,只有一种方法可以将头部从列表的尾部分割出来.

没有什么特别的::对比+:你可以使用,+如果你有一个预定的想法,你想要它打破一个数字.例如,如果你想+表示"分成两半",那么你可以这样做:

object + {
    def unapply(i: Int) = Some(i-i/2, i/2)
}
Run Code Online (Sandbox Code Playgroud)

并使用它像:

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

scala> val c + d = 5
c: Int = 3
d: Int = 2
Run Code Online (Sandbox Code Playgroud)

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