美文网首页
Scala 模式匹配

Scala 模式匹配

作者: wangdy12 | 来源:发表于2018-03-12 17:13 被阅读0次

样本类 case class

类前加上case修饰符,编译器会添加额外的语法,更好的支持模式匹配

  • 添加与类名称相同的工厂方法
  • 样本类参数列表中的所有参数,自动添加前缀val
  • 添加toString, hashCode,equals方法
  • 添加copy方法,方便进行复制,同时修改部分参数(默认参数和命名形参结合)
//定义一个表达式和一元运算
abstract class Expr
case class UnOp(operator: String, arg: Expr) extends Expr

反编译Expr.class,UnOp.class和UnOp$.class,查看具体添加的方法


iExpr.class
UnOp.class UnOp$.class

模式匹配 Pattern Match

Scala中的匹配表达式(match expression)类似于Java的switch,不过匹配一个之后就会返回(等同于隐式添加了break),如果都没有匹配到抛出MatchError异常
不过Scala先写选择表达式

//Scala
selector match { alternatives }
//Java
switch (selector) { alternatives }

模式匹配包含一序列的选项,开头是case,每个选项包含一个模式,中间是箭头分隔,右侧是一个或多个表达式,按代码的先后顺序比较每个模式

case pattern => expressions

模式的种类

通配符模式 wildcard pattern
_匹配所有值,但没有变量引用匹配到的值,用来忽略对象中不关心的部分

expr match {
   case BinOp(_, _, _) => println(expr + " is a binary operation")
    case _ => // 处理默认情况,返回值为unit值的()
}

常量模式 constant pattern
只匹配自身,任何字面量都可以做常量,val和单例对象也可以做常量

变量模式 variable pattern
类似于通配符匹配,匹配任何对象,在case语言的右侧,变量可以引用匹配到的值
区分:以小写字母开始的名称被当做是变量模式,否则当做常量
可以使用反引号包住变量名称,它将会被理解为常量

val v42 = 42
Some(3) match {
  case Some(`v42`) => println("42") //不用反引号,理解为变量,一直输出42
  case _ => println("Not 42") //输出
}

构造器模式 constructor pattern
构造器的参数也可以是模式(深度匹配)

case BinOp("+", e, Number(0)) => println("a deep match") //三层匹配

序列模式 Sequence pattern
匹配序列类型List,Array等,_*作为模式的最后一个元素,匹配任意数量的元素

case List(0, _, _) => println("found it")//匹配从零开始的,有三个元素的列表
case List(0, _*) => println("found it")//无论任意长度,以零开头的列表
case _ =>

元组模式 Tuple pattern

case (a, b, c) => println("matched " + a + b + c)

类型模式 Type pattern
用于类型测试和类型转换

def generalSize(x: Any) = x match {
  case s: String => s.length
  case m: Map[_, _] => m.size//类型模式中的下划线是通配符
  case _ => -1
}

Scala中的类型测试和转换故意很冗长,不推荐使用

if (x.isInstanceOf[String]) {
  val s = x.asInstanceOf[String]
  s.length
} else ...

由于类型擦除,不能指定泛型的类型进行匹配

case m: Map[Int, Int] => true //无论什么类型都是true

变量绑定 Variable binding
除了变量模式之外,还可以将变量添加到任何其他模式
变量名称 @ 模式, 变量绑定模式,如果模式成功,该变量设置为匹配的对象

case UnOp("abs", e @ UnOp("abs", _)) => e

模式守卫 pattern guard

模式守卫接在模式之后,以if开头,之后任意的布尔表达式,为真时,匹配才会成功

case BinOp("+", x, y) if x == y =>
     BinOp("*", x, Number(2))

密封类 sealed class

目的是让Scala编译器来检测匹配表达式中缺失的模式组合

通过密封样本类的超类,密封的类不能添加任何新的子类,除了同一个文件中的子类。这样编译器可以确认子类,会通过警告信息表明缺少的模式组合

sealed abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
//产生警告
def describe(e: Expr): String = e match {
  case Number(_) => "a number"
  case Var(_) => "a variable"
}

//通过注解抑制警告
def describe(e: Expr): String = (e: @unchecked) match {
  case Number(_) => "a number"
  case Var(_) => "a variable"
}

Option类型

Scala定义了一个名为Option的标准类型用于表示可选值。这样的值可以有两种形式:Some(x),其中x是实际值,或者是None对象,表示缺失的值。
Scala集合中的一些标准操作会产生可选值,例如Scala的Map的get方法会生成Some(x)或返回None。

def show(x: Option[String]) = x match {
  case Some(s) => s
  case None => "?"
}

使用PartialFunction

花括号中的case序列可以当做广义的函数字面量,正常的函数字面量只有一个入口点和参数列表,case序列可以有多个入口点,每个case语句就是一个入口点,对应有自己的参数列表

val withDefault: Option[Int] => Int = {
    case Some(x) => x
    case None => 0
}

该例子中有两个case,对应两个入口点

case序列写作偏函数,可以避免匹配错误的情况

val second: PartialFunction[List[Int],Int] = {
   case x :: y :: _ => y
}

以上函数会被翻译为

new PartialFunction[List[Int], Int] {
  def apply(xs: List[Int]) = xs match {
    case x :: y :: _ => y
  }
  def isDefinedAt(xs: List[Int]) = xs match {
    case x :: y :: _ => true
    case _ => false
  }
}

偏函数中的isDefinedAt方法,用来测试该函数对特定的值是否可用,在调用真正函数之前会先进行测试

相关文章

  • Scala模式匹配及偏函数

    模式匹配公式: 一、代码Demo 二、Scala中的模式匹配处理异常 三、Scala函数

  • Scala学习笔记(八) 模式匹配

    1. 模式匹配简介 模式匹配是 Scala 的重要特性之一,前面两篇笔记Scala学习笔记(六) Scala的偏函...

  • Case Class与模式匹配

    模式匹配入门 在java语言中存在switch语句,例如: 上述scala代码展示了如何使用scala中的模式匹配...

  • scala模式匹配

    以下是常见的scala模式匹配实例。 variableName @ pattern 下面这个示例 模式匹配中cas...

  • scala模式匹配

    1.scala是匹配和java中的switch的区别: ...

  • scala 模式匹配

    scala的模式匹配与java的switch case相似,但是switch case只能对值进行判断,scala...

  • Scala 模式匹配

    样本类 case class 类前加上case修饰符,编译器会添加额外的语法,更好的支持模式匹配 添加与类名称相同...

  • Scala 模式匹配

    一、模式匹配基本使用 说明: => 后的代码可以写多行且不用 { } 模式匹配也是表达式,所以它也可以赋值给一个变...

  • scala模式匹配

    基本类型模式匹配 数组匹配 List匹配 类型匹配 case匹配 Some | None匹配

  • scala:模式匹配

    知识点: 模式匹配 提取器

网友评论

      本文标题:Scala 模式匹配

      本文链接:https://www.haomeiwen.com/subject/ngkryxtx.html