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

问题描述

我刚开始学习 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())。到目前为止还好。但是定义的只是 Succ() 而不是一种 Prev()?

解决方法

在这种情况下,prev 在 case 语句中声明,这里:

case Succ(prev) => add(prev,Succ(m))

当您输入 case Succ(prev) ... 时,您正在使用模式匹配,并说:如果 nSucc 类型,我们称其 n 参数为 prev ,然后返回 add(...)

所以基本上你将 Succ 类的 n 参数命名为 prev 以在箭头 => 之后使用它

这个 Scala 功能甚至可以与正则表达式一起使用,您可以在其中捕获将放入您定义的变量中的组。

有关文档的更多信息:https://docs.scala-lang.org/tour/pattern-matching.html

,

Scala 为您提供简洁的语法,因此您不必写出类似的东西

case Succ(prev) => add(prev,...)

我们可以通过考虑数据的结构来进行更高层次的推理并简单地编写

Private checkpopup As class_checkpopup Public Sub checkbox_popup_fund(table) Set checkpopup = New class_checkpopup Let checkpopup.table = table checkpopup.Show Debug.Print checkpopup.table End Sub

,

case classes 在 scala 中自动定义一个名为 unapply 的方法。

这是Scala 2 Doc on Case Classes

正是这种 unapply 方法启用了这种模式匹配。

如果我使用名为 value 的成员定义一个 case 类,我可以通过使用 unapply 来获取它来提取该值:

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)) 时,您通过匹配 n 方法的类型签名将 Succ 的值 prev 提取为 unapply。>

因此,定义了 prev,它是匹配的 n 包含的值 Succ