Skip to content

模式匹配 ​

模式只出现在 switch case 等明确的匹配位置,用于测试形状并绑定局部名称。它不是任意布尔表达式。

模式形式 ​

首版模式包括 variant、类型化绑定、通配符 _、字面量和 null。variant 的每个数据位置再次接受完整模式,因此模式可以递归嵌套。

norm
enum Tree<T> {
    Leaf(T value),
    Branch(Tree<T> left, Tree<T> right)
}

case Branch(Leaf(Integer value), _) {
    printLine(value)
}

variant 名必须属于该位置的 enum。参数顺序必须与 variant 声明一致;末尾带默认值的数据位置可以省略,语义等同于 _。Integer value 是类型化绑定:模式成功时,以声明类型把匹配值绑定到 value;名称只在当前 case 块内可见。

_ 匹配任意值且不绑定名称。字面量按该类型的语言内建相等语义匹配,且必须与所在位置的静态类型兼容。null 只匹配 nullable 位置的 null 值。

norm
case Leaf(0) { printLine("zero") }
case Leaf(null) { printLine("missing nullable value") }
case _ { printLine("other") }

类型化绑定可以使用被匹配值的静态类型或其名义子类型;使用子类型时检查动态类型并绑定收窄后的值。成员形状不参与匹配。

可空类型绑定同时匹配 null 和该类型的非空值:String? text 可以绑定 null,String text 只匹配非空字符串。可空子类型绑定不会覆盖其他非空子类型;穷尽性与不可达分支检查使用相同规则。

泛型类型模式保留完整类型实参,Box<Integer> 不匹配 Box<String>;Box<T> 使用当前调用的实化类型参数。下面的可执行示例还组合了枚举模式、switch 结果与 if 结果:

norm
enum Delivery {
  Pending,
  Sent(String trackingCode),
  Failed(String reason)
}

class Box<T> {
  T item
}

String describe(Delivery delivery) {
  switch delivery {
    case Pending { break "waiting" }
    case Sent(String code) { break "tracking " + code }
    case Failed(String reason) { break "failed: " + reason }
  }
}

Boolean matches<T>(Any candidate) {
  switch candidate {
    case Box<T> box { break true }
    case _ { break false }
  }
}

String nextAction(Delivery delivery, Boolean notify) {
  String action = if notify { "notify" } else { "record" }
  String state = switch delivery {
    case Pending { break "pending" }
    case Sent(_) { break "sent" }
    case Failed(_) { break "failed" }
  }
  action + " " + state
}

main() {
  Delivery sent = Delivery.Sent(trackingCode: "N-42")
  Delivery failed = Delivery.Failed(reason: "address")
  printLine(describe(sent))
  printLine(describe(failed))
  printLine(nextAction(delivery: Delivery.Pending, notify: true))
  printLine(nextAction(delivery: sent, notify: false))

  Any number = Box<Integer>(item: 7)
  printLine(matches<Integer>(number))
  printLine(matches<String>(number))
}

匹配过程 ​

单个模式由外到内、同层从左到右检查。失败不会留下局部绑定或其他可观察状态。case 按源码顺序选择首个匹配模式;被前序模式完全覆盖的 case 不可达并产生编译错误。模式只检查 enum variant、名义类型和值,不调用用户定义的匹配协议。

Norm 0.25