一.scala模式匹配(pattern matching)

pattern matching可以说是scala中十分强大的一个语言特性,当然这不是scala独有的,但这不妨碍它成为scala的语言的一大利器。

scala的pattern matching是类似这样的,

  1. e match {
  2. case Pattern1 => do Something
  3. case Pattern2 if-clause => do others
  4. ...
  5. }

其中,变量e后面接一个match以及一个代码块,其中每个case对应一种可能回匹配的类型,如果匹配成功则执行=>后面的代码。

我们可以用一个具体一些的例子来看看模式匹配是怎么工作的:

  1. case class Player(name: String, score: Int)
  2. def printMessage(player: Player) = player match {
  3. case Player(_, score) if score > 100000 =>
  4. println("Get a job, dude!")
  5. case Player(name, _) =>
  6. println("Hey, $name, nice to see you again!")
  7. }

看起来有点类似于其他语言的switch,但其实还是有很大的不同的。

以java的switch为例,java的switch仅仅会做一些基本类型的匹配,然后执行一些动作,并且是没有返回值的。

而scala的pattern matching match则要强大得多,除了可以匹配数值,同时它还能匹配类型。

  1. def parseArgument(arg: String) = arg match {
  2. //匹配值
  3. case "-h" | "--help" => displayHelp
  4. case "-v" | "--version" => displayVerion
  5. case whatever => unknownArgument(whatever)
  6. }
  1. def f(x: Any): String = x match {
  2. //匹配类型
  3. case i:Int => "integer: " + i
  4. case _:Double => "a double"
  5. case s:String => "I want to say " + s
  6. }

同时pattern matching是有返回值的,比如上面的match,它返回的就是一个Unit。我们也可以修改上面的代码让它返回一个字符串:

  1. case class Player(name: String, score: Int)
  2. def message(player: Player) = player match {
  3. case Player(_, score) if score > 100000 =>
  4. "Get a job, dude!"
  5. case Player(name, _) =>
  6. "Hey, $name, nice to see you again!"
  7. }

值得一提的是,pattern matching 返回值是由第一个匹配的模式中的代码块决定的。

二. 为什么要用pattern matching

看到这里你会发现一个问题,pattern matching不是和if else差不多吗?那为什么还要使用pattern matching呢?

首先我们需要明白,模式匹配其实本质上是提供一个方便的解构(Destructuring)数据结构的方式,以scala为例,pattern matching其实用到了scala中提取器的功能,提取器其实就是类中的unapply()方法。

  1. trait User {
  2. def name: String
  3. }
  4. class FreeUser(val name: String) extends User
  5. object FreeUser {
  6. //提取器
  7. def unapply(user: FreeUser): Option[String] = Some(user.name)
  8. }
  1. val user: User = new FreeUser("Daniel")
  2. user match {
  3. case FreeUser(name) => println("it match here" + name)
  4. case _ => println("not me")
  5. }

明白了模式匹配的本质你就会直到,其实if else只是pattern matching中的一个典型的用法,但并非它的全部。

同时,pattern matching允许你解耦两个并不真正属于彼此的东西,也使得你的代码更易于测试。比如上面的match部分的代码我们可以写成下面这样:

  1. val user: User = new FreeUser("Daniel")
  2. //将返回结果存在一个常量中
  3. val message = user match {
  4. case FreeUser(name) => "it match here" + name
  5. case _ => "not me"
  6. }
  7. //可以随意使用该常量,实现解耦
  8. println(message)

这样会赋予代码更多的灵活性,同时也更加方便做进一步操作。

而以可读性的角度来说,使用一大堆的if else代码无疑是比较难看的,而如果使用pattern matching的话,代码会简洁清晰很多,而简洁的代码则会更容易阅读。

参考文章:

https://doc.yonyoucloud.com/doc/guides-to-scala-book/chp3-pattern-everywhere.html

https://www.zhihu.com/question/30354775


推荐阅读:

从分治算法到 MapReduce

大数据存储的进化史 --从 RAID 到 Hdfs

scala模式匹配详细解析的更多相关文章

  1. (转)linux应用之test命令详细解析

    linux应用之test命令详细解析 原文:https://www.cnblogs.com/tankblog/p/6160808.html test命令用法. 功能:检查文件和比较值 1)判断表达式 ...

  2. java类生命周期详细解析

    (一)详解java类的生命周期 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前 ...

  3. springmvc 项目完整示例06 日志–log4j 参数详细解析 log4j如何配置

    Log4j由三个重要的组件构成: 日志信息的优先级 日志信息的输出目的地 日志信息的输出格式 日志信息的优先级从高到低有ERROR.WARN. INFO.DEBUG,分别用来指定这条日志信息的重要程度 ...

  4. include_path详细解析

    include_path详细解析     原文地址:http://www.laruence.com/2010/05/04/1450.html 1.php默认的包含路径为 .;C:\php\pear 即 ...

  5. Intent的详细解析以及用法

    Intent的详细解析以及用法      Android的四大组件分别为Activity .Service.BroadcastReceiver(广播接收器).ContentProvider(内容提供者 ...

  6. C++多态的实现及原理详细解析

    C++多态的实现及原理详细解析 作者: 字体:[增加 减小] 类型:转载   C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型 ...

  7. 对MySQL DELETE语法的详细解析

    以下的文章主要描述的是MySQL DELETE语法的详细解析,首先我们是从单表语法与多表语法的示例开始的,假如你对MySQL DELETE语法的相关内容十分感兴趣的话,你就可以浏览以下的文章对其有个更 ...

  8. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

  9. 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式

    单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式     一 表结构如下:  万行 CREATE TABLE t_audit_operate_log (  Fid b ...

随机推荐

  1. JavaScript基础——深入学习async/await

    本文由云+社区发表 本篇文章,小编将和大家一起学习异步编程的未来--async/await,它会打破你对上篇文章Promise的认知,竟然异步代码还能这么写! 但是别太得意,你需要深入理解Promis ...

  2. 使用Laya引擎开发微信小游戏(下)

    本文由云+社区发表 6. 动画 6.1 创建伞兵对象 在src目录下创建一个新目录role,用来存放游戏中角色. 在role里创建一个伞兵Soldier.ts对象文件. module role{ ex ...

  3. 使用字面量,比new更加有效

    参考原文:http://www.cnblogs.com/yxf2011/archive/2012/04/01/2428225.html http://www.cnblogs.com/mushishi/ ...

  4. Perl处理数据(一):s替换、split和join

    s替换 m//模式用来匹配文本,也就是说用来找数据.而s///用来查找并替换文本,所以可以用来处理文本文件.在有了正则的基础之后,s///用起来会简单很多. 用法格式为: $str =~ s/reg/ ...

  5. Perl包相关

    名称冲突问题 假如在sum2.pm中使用require导入了一个代码文件sum1.pm: #!/usr/bin/env perl use strict; use warnings; use 5.010 ...

  6. 基于stm32的水质监测系统项目基础部分详细记录

    基于stm32的水质监测系统项目基础部分详细记录 软件环境:MDK5 硬件环境:STM32F103ZET6 开发板.颜色传感器.串口屏.串口打印机 搭建工程模板 在进行项目软件的撰写时,首先新建一个基 ...

  7. 同一个dll 不同路径下注册 一个失败 一个成功

    一个路径下用regsvr32注册成功,一个注册失败,提示平台不兼容. 最后用depends查看依赖的dll,发现依赖的dll有问题,从注册成功的路径下复制一个过来,重新注册就成功了

  8. 22.QT-QXmlStreamReader解析,QXmlStreamWriter写入

    XML介绍 XML 用于存储数据,数据的形式类似于树结构(参考: http://www.runoob.com/xml/) 示例如下 <?xml version="1.0" e ...

  9. windows10系统盘瘦身

  10. Java学习笔记之——this关键字、非静态成员属性和静态成员属性的区别、类的加载顺序

    一.this关键字 1.代表当前类的对象 2.通过” . ”调用成员属性和成员方法 3.通过this可以区分成员属性和参数 参数名和属性名相同的情况,默认是参数名 二.非静态成员属性和静态成员属性的区 ...