在java中有switch/case这样的模式匹配语句,可以匹配的类型包括int,byte,char,short, enum,在java8又支持了字符串。

在scala中也有类似的模式匹配语句,即match-case。这个好现在之前使用过一次。scala中的match-case匹配的类型更为广泛,它是对Any类型起作用的。

来看个例子:

def activity(day: String) {
day match {
case "Sunday" => println("Eat, sleep, repeat... ")
case "Saturday" => println("Hangout with friends... ")
case "Monday" => println("...code for fun...")
case "Friday" => println("...read a good book...")
}
} List("Monday", "Sunday", "Saturday").foreach {
activity
}

执行结果:

有没有注意到,这里和java是有些不一样的,最大的区别是没有break。但是在匹配上了后,也不会继续顺序执行了。其实我一直觉得java的那个switch/case在这一点上是有些不足的,这次总算是在scala中解决了。不过这里也有些让人不爽的地方:比如没有匹配到就会抛出异常。不管怎样,这个异常是不能随意抛出的。在Java的switch/case中,是有一个default来处理那些没有匹配到的内容的。在scala中也有一个特殊的符号起到了类似的作用,就是“_”,这里的下划线是一个通配符。继续修改下上面的代码:

def activity(day: String) {
day match {
case "Sunday" => println("Eat, sleep, repeat... ")
case "Saturday" => println("Hangout with friends... ")
case "Monday" => println("...code for fun...")
case "Friday" => println("...read a good book...")
case _ => println("...nothing...")
}
} List("Monday", "Sunday", "Saturday", "Tuesday").foreach {
activity
}

就不贴执行结果了。

需要注意的是:case表达式并不限于在match语句里使用。这里,包含case表达式的代码块就是一个简单函数值。

刚才说过match-case支持的类型是Any。在java支持的基本类型、枚举和字符串之外,scala也支持其他任意类型的实例,比如列表和元组:

def processCoordinates(input: Any) {
input match {
case (a, b) => printf("Processing (%d, %d)... ", a, b)
case List("red", "blue", "white") => println("Stars and Stripes...")
case List("red", "blue", _*) => println("colors red, blue, ... ")
case "done" => println("done")
case _ => null
}
}
processCoordinates((39, -104))
processCoordinates("done")
processCoordinates(List("red", "blue", "green"))
processCoordinates (List("red", "blue", "white"))

看下执行结果:

前面有一段警告,可以不去管它。

不过代码里却是有些不足之处,其中对元组的匹配还可以更细致些,比如针对不同类型的值可以做不同的处理:

def process(input: Any) {
input match {
case (a: Int, b: Int) => print("Processing (int, int)... ") -
case (a: Double, b: Double) => print("Processing (double, double)... ")
case msg: Int if (msg > 1000000) => println("Processing int > 1000000")
case msg: Int => print("Processing int... ")
case msg: String => println("Processing string... ") -
case _ => printf("Can't handle %s... ", input)
}
} process ((34.2, -159.3))
process(0)
process(1000001)
process (2.2)

代码中演示了在case语句里如何为单一的值和元组元素指定类型。除了类型之外,还可以使用卫述句(guard)。卫述句用if从句表示,在模式匹配里,对表达式求值前必须满足卫述句。

看下结果:

case的顺序很重要。Scala会自上而下地求值。所以,上面代码5和6两行是不能交换的。

##########

scala学习手记39 - 模式匹配的更多相关文章

  1. scala学习手记40 - 使用case类

    前面两节我们已经多次接触过case关键字了.case关键字不仅可以用在match/case中来执行模式匹配,也可以用来修饰类.不过用case修饰的类也主要是用来做模式匹配.在上一节曾经提到过match ...

  2. scala学习手记38 - 方法命名约定和for表达式

    方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. ...

  3. scala学习手记23 - 函数值

    scala的一个最主要的特性就是支持函数编程.函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套.这些高阶函数称为函数值. 举一个简单的例子 ...

  4. scala学习手记17 - 容器和类型推断

    关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var ...

  5. scala学习手记8 - 自适应的默认做法

    scala有一些默认做法,会让代码更简洁.更易读写,下面列出了这样几个特性: 1. 支持脚本.scala支持脚本,因此无须将所有的代码都放到类里.如果脚本可以满足需求,就将代码放到一个脚本里,无须再创 ...

  6. Scala学习手记1 - 快速体验

    又重新开始了scala的学习,因为中断了太长时间,所以这次还得从零开始.学习的过程就记录在这个博客上了. 这次学习的教程是<scala程序设计 java虚拟机多核编程实战>,我在多看上买了 ...

  7. Scala学习十四——模式匹配和样例类

    一.本章要点 match表达式是更好的switch,不会有意外调入下一个分支 如果没有模式能够匹配,会抛出MatchError,可以用case _模式避免 模式可以包含一个随意定义的条件,称做守卫 你 ...

  8. scala学习手记40 - case表达式里的模式变量和常量

    再来看一下之前的一段代码: def process(input: Any) { input match { case (a: Int, b: Int) => println("Proc ...

  9. scala学习手记37 - 容器的使用

    这次统一看一下scala中容器类的几个方法. Set filter()方法 filter()方法用来从Set中过滤获取含有指定特征的元素.示例代码如下: val colors1 = Set(" ...

随机推荐

  1. ssh访问跳过RSA key"yes/no"验证

    通常我们再批量配置多台机器的时候经常出现通过ssh批量登录机器提示 RSA key fingerprint is ::a6:b1:c9:d7:b8::c1:::8e:f5::2b:8b. Are yo ...

  2. Design Pattern - 命令模式

    一般执行一个操作的过程, 创建对象, 并调用对象的函数, 函数执行, 返回 比如下面的类图, client直接调用Receiver.action 而命令模式, 抽象出command对象, 并在comm ...

  3. Java基础语法 - 面向对象 - static 关键字

    使用static关键字修饰的变量.常量和方法分别被称作静态变量.静态常量和静态方法,也被称作类的静态成员 静态变量 使用static修饰过的类变量称为静态变量 该变量需要使用类名.变量名进行调用,不能 ...

  4. js身份证号有效性验证

    1.简述 最近做的系统有用到实名验证的,起初对于用户身份证号只是简单地使用正则表达式进行验证, 很多无效的身份证号就成了漏网之鱼. 导致后台存表里很多无效的身份证号,随便输入用户名和身份证号就可以实名 ...

  5. day3-python-文件操作(2)

    本文内容涉及python中的os模块和os.path模块的常用操作,这两个模块提供了与平台和操作系统无关的文件系统访问方法.os模块负责大部分的文件系统操作,包括:删除文件.重命名文件.遍历目录树等: ...

  6. ImageMagick来处理图片,缩放,调整高度等操作

    单个缩放图片 convert 911.jpg -resize 25% 911.jpg 前面是要处理的图片路径,后面是输出的图片路径,我这么写就把原先图片缩放了 批量缩放图片 mogrify -samp ...

  7. LeetCode:N叉树的后序遍历【590】

    LeetCode:N叉树的后序遍历[590] 题目描述 给定一个 N 叉树,返回其节点值的后序遍历. 例如,给定一个 3叉树 : 返回其后序遍历: [5,6,3,2,4,1]. 题目分析 这道题有好几 ...

  8. 微信小程序 canvas 生成随机验证码

    转载:https://blog.csdn.net/qq_16646819/article/details/81020245?utm_source=blogxgwz0 js // pages/bind/ ...

  9. hibernatetemplate find条件查询方法

    一.find(String queryString); 示例:this.getHibernateTemplate().find("from bean.User"); 返回所有Use ...

  10. Loadrunder场景设计篇——定时器(schedule)

    A.   定义方案schedule 在 Scenario Schedule面板中,选择一个方案schedule,或通过点击New Schedule定义一个新的方案 定义schedule: a.新建sc ...