1

我以为我可以通过 unapply 将 n+k 模式实现为 scala 中的活动模式,但它似乎失败了unspecified value parameter: k

object NPlusK {
    def apply(n : Int, k : Int) = {
        n + k
    }    

    def unapply(n : Int, k : Int) = {
        if (n > 0 && n > k) Some(n - k) else None
    }
}

object Main {
    def main(args: Array[String]): Unit = {

    }

    def fac(n: Int) : BigInt = {
        n match {
            case 0 => 1
            case NPlusK(n, 1) => n * fac(n - 1)
        }
    }
}

是否可以在 Scala 中实现 n+k 模式,在这种情况下如何实现?

4

2 回答 2

4

您应该查看这个问题以进行更长时间的讨论,但这里是针对您的具体情况的简短改编。

一个unapply方法只能接受一个参数,并且必须根据该参数决定如何将其分成两部分。由于有多种方法可以将某个整数x分成nk使得x = n + k,因此您不能使用 an unapply

您可以通过为每个k创建单独的提取器来解决它。因此,而不是NplusK你有Nplus1,Nplus2等,因为只有一种方法可以从x中获取n ,使得x = n + 1

case class NplusK(k: Int) {
  def unapply(n: Int) = if (n > 0 && n > k) Some(n - k) else None
}

val Nplus1 = NplusK(1)

val Nplus1(n) = 5  // n = 4

所以你的比赛变成:

    n match {
        case 0 => 1
        case Nplus1(n) => n * fac(n - 1)
    }
于 2012-05-11T20:46:14.500 回答
3

解构器 unapply 根本不能以这种方式工作。它只接受一个参数,即匹配值,并返回元组上的一个选项,其中包含与您的模式 (NPlusK) 的参数一样多的元素。也就是说,当你有

(n: Int) match {
   ...
   case NPlusK(n, 1)

它将寻找unapply带有Int(或超类型)参数的方法。如果有这样的方法,并且返回类型是 a Tuple2(因为 NPlusK 在模式中出现了两个参数),那么它将尝试匹配。无论 NPlusK 内部有什么子模式(这里是变量 n 和常量 1),无论如何都不会被传递给 unapply(如果你写的话,你期望什么case NPlusK(NPlusK(1, x), NPlusK(1, y))?)。相反,如果 unapply 返回一些元组,那么元组的每个元素都将匹配到相应的子模式,这里n总是匹配,如果值等于 1,则匹配 1。

你可以写

def unapply(n: Int) = if (n > 0) Some((n-1, 1)) else None.  

当你的NPlusK(n, 1). 但这不会匹配NPlusK(n, 2), 也不会NPlusK(1, n)(除非n是 2)。这没有多大意义。一个模式应该可能只有一个可能的匹配项。NPlusK(x, y)可以通过许多不同的方式进行匹配n

什么会起作用的是 Peano 整数之类的Succ(n)匹配n+1.

于 2012-05-11T20:35:27.363 回答