scala中的递归模式匹配:为什么我可以匹配未定义的变量?

ekqde3dh  于 2021-07-14  发布在  Java
关注(0)|答案(3)|浏览(342)

我刚开始学习scala,找到了一段代码,这很好,但我不明白为什么。。。

sealed abstract class Nat

  case class Zero() extends Nat

  case class Succ(n: Nat) extends Nat

  def add(n: Nat, m: Nat): Nat = {
    n match  {
    case Zero() => m
    case Succ(prev) => add(prev, Succ(m))
    }
  }

nat和zero的成员在一个额外文件中定义(稍后使用),如下所示:

val zero = Zero()
 val one = Succ(zero)
 val two = Succ(one)
 val three = Succ(Succ(one))
 val four = Succ(Succ(two))

我现在的问题是:在第二种情况下,“prev”从未得到定义。这里发生了什么?后面的数学对我来说很清楚,(比如n+m==(n-1)+(m+1),重复直到n==zero()。到目前为止还可以。但是所有的定义都是such(),而不是prev()?

6xfqseft

6xfqseft1#

在这种情况下, prev 在case语句中声明,如下所示: case Succ(prev) => add(prev, Succ(m)) 当你打字的时候 case Succ(prev) ... 你正在使用模式匹配,并说:如果 n 属于类型 Succ 我们称之为 n 参数 prev ,然后返回 add(...) 因此,基本上您将succ类的n参数命名为prev,以便在箭头后面使用它 => 这个scala特性甚至可以与regex一起使用,在regex中您可以捕获将放入您定义的变量中的组。
有关文档的更多信息:https://docs.scala-lang.org/tour/pattern-matching.html

thtygnil

thtygnil2#

scala为您提供了简洁的语法,因此不必编写

if (n.isInstanceOf[Succ]) {
  val x = n.asInstanceOf[Succ]
  val prev = x.n
  add(prev, ...)
}

我们可以通过考虑数据的结构在更高的层次上进行推理并简单地编写 case Succ(prev) => add(prev, ...)

eqfvzcg8

eqfvzcg83#

case class scala中的es自动定义一个名为 unapply .
下面是关于案例类的scala 2文档
就是这个 unapply 启用这种模式匹配的方法。
如果我用一个名为 value ,我可以通过使用此函数来提取该值:

case class Number( value: Int )

val valueOfNumber: Int = Number(5).value
println(valueOfNumber) // 5

// Using unapply

val testNumber: Number = Number(200)
val Number(numberValue) = testNumber
println(numberValue) // 200

当你这么做的时候 case Succ(prev) => add(prev, Succ(m)) 您正在提取值 nSucc 作为 prev 通过匹配 unapply 方法。
因此, prev 是定义的,是值, n ,包含在匹配的 Succ

相关问题