Scala Pattern Matching

本文深入探讨Scala中的模式匹配,从常量模式、变量模式、通配符模式、构造器模式、类型模式到变量绑定模式,详细解析每种模式的用法及应用实例。

Scala Pattern Matching


在 scala里对pattern有明确的定义,在形式上有以下几种pattern:

1) 常量模式(constant patterns) 包含常量变量和常量字面量

如下所示的scala 脚本,就是一个常量模式匹配

val message = "hello world"

message match {
  case "hello world" => println("ok")
}

运行,

C:\WorkSpace6-scala\scala-train\src\com\usoft>scala pattern-match.scala
ok


2) 变量模式(variable patterns)

确切的说单纯的变量模式没有匹配判断的过程,只是把传入的对象给起了一个新的变量名。

val message = "hello world"

message match {
  case whateverName => println(whateverName)
}

上面把要匹配的 site对象用 whateverName 变量名代替,所以它总会匹配成功。不过这里有个约定,对于变量,要求必须是以小写字母开头,否则会把它对待成一个常量变量,比如上面的whateverName 如果写成WhateverName就会去找这个WhateverName的变量,如果找到则比较相等性,找不到则出错。


变量模式通常不会单独使用,而是在多种模式组合时使用,比如

List(1,2) match{ case List(x,2) => println(x) }

里面的x就是对匹配到的第一个元素用变量x标记。


3) 通配符模式(wildcard patterns)

通配符用下划线表示:"_" ,可以理解成一个特殊的变量或占位符。

单纯的通配符模式通常在模式匹配的最后一行出现,case _ => 它可以匹配任何对象,用于处理所有其它匹配不成功的情况。

通配符模式也常和其他模式组合使用:

scala> List(1,2,3) match{ case List(_,_,3) => println("ok") }

上面的 List(_,_,3) 里用了2个通配符表示第一个和第二个元素,这2个元素可以是任意类型

通配符通常用于代表所不关心的部分,它不像变量模式可以后续的逻辑中使用这个变量。


4) 构造器模式(constructor patterns)

这个是真正能体现模式匹配威力的一个模式!

我们来定义一个二叉树:

//抽象节点
trait Node

//具体的节点实现,有两个子节点
case class TreeNode(v: String, left: Node, right: Node) extends Node

//Tree,构造参数是根节点
case class Tree(root: TreeNode)

val tree = Tree(TreeNode("root", TreeNode("left", null, null), TreeNode("right", null, null)))

tree.root match {
  case TreeNode(_, TreeNode("left", _, _), TreeNode("right", null, null)) => println("ok ok ok")
}

如果我们期望一个树的构成是根节点的左子节点值为”left”,右子节点值为”right”并且右子节点没有子节点

那么可以用下面的方式匹配:

tree.root match {
  case TreeNode(_, TreeNode("left", _, _), TreeNode("right", null, null)) =>
    println("bingo")
}


5) 类型模式(type patterns)

类型模式很简单,就是判断对象是否是某种类型:

"hello world" match {
  case _: String => println("ok")
}

跟 isInstanceOf 判断类型的效果一样,需要注意的是scala匹配泛型时要注意,

比如

def foo(a: Any) = a match {
  case a: List[String] => println("ok");
  case _ =>
}

如果使用了泛型,它会被擦拭掉,如同java的做法,所以上面的 List[String] 里的String运行时并不能检测

foo(List("A")) 和 foo(List(2)) 都可以匹配成功。实际上上面的语句编译时就会给出警告,但并不出错。

通常对于泛型直接用通配符替代,上面的写为 case a : List[_] => …


6) 变量绑定模式 (variable binding patterns)

这个和前边的变量模式有什么不同?看一下代码就清楚了:

依然是上面的TreeNode,如果我们希望匹配到左边节点值为”left”就返回这个节点的话:

tree.root match {
  case TreeNode(_, leftNode@TreeNode("left", _, _), _) => leftNode
}

用@符号绑定 leftNode变量到匹配到的左节点上,只有匹配成功才会绑定


转载于:https://my.oschina.net/xinxingegeya/blog/399962

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值