当前位置: 首页 > news >正文

Scala 样本类和模式匹配

  样本类(case clas)和模式匹配(pattern matching),在编写规范的、无封装数据结构时会用到的构件。对于树型递归数据尤其有用。


 

一、简单例子:  

1 abstract class Expr
2 case class Var(name:String) extends Expr
3 case class Number(num:Double) extends Expr
4 case class UnOp(operator : String , arg : Expr) extends Expr
5 case class BinOp(operator : String , left : Expr , right : Expr) extends Expr

  样本类:添加了case的类便是样本类。这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定。如下:

  1. 添加与类名一致的工厂方法。也就是说,可以写成Var("x")来构造Var对象。
  2. 样本类参数列表中的所有参数隐式获得了val前缀,因此它被当作字段维护。
  3. 编译器为这个类添加了方法toString,hashCode和equals等方法。

  模式匹配: 

1 def simplifyTop(expr : Expr) : Expr = expr match{
2 case UnOp("-" , UnOp("-" , e)) => e
3 case BinOp("+" , e , Number(0)) => e
4 case BinOp("*" , e , Number(1)) => e
5 case _ => expr
6 }
                    清单 15.1

  match对应Java里的switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。

  一个模式匹配包含了一系列备选项,每个都开始于关键字case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

  match表达式通过以代码编写的先后次序尝试每个模式来完成计算。类似于UnOp("-" , UnOp("-" , e))这种形式的,是构造器模式匹配。

  match与switch的比较:匹配表达式可以被看作Java风格Switch的泛化。但有三点不同:

  1. match是Scala的表达式,始终以值作为结果;
  2. Scala的备选项表达式永远不会“掉到”下一个case;
  3. 如果没有模式匹配,MatchError异常会被抛出。这意味着必须始终确信所有的情况都考虑到了,或者至少添加一个默认情况什么都不做。如 case _ => 

二、模式的种类

通配模式:case _ => 。表示默认的全匹配备选项。通配模式还可以用来忽略对象中不关心的部分。如:case BinOp(_,_,_) => XXX,则表示不关心二元操作符的元素是什么,只是检查是否为二元操作符

常量模式 :仅匹配自身。任何字面量都可以用作常量。包括String类型。另外,任何的val或单例对象也可以被用作常量。如,单例对象Nil是只匹配空列表的模式。

变量模式 :变量模式类似于通配符,可以匹配任何对象。不同点在于,Scala把变量绑定在匹配的对象上。之后就可以使用这个变量操作对象。如:

expr match{
case 0 => "zero"
case somethingElse => "not zero" + somethingElse
}
          清单 15.6

  有一个注意点:Scala使用了一个简单的文字规则来区分是一个常量还是一个变量:用小写字母开始的简单名被当作是模式变量。

构造器模式:它的存在使得模式匹配真正变得强大。它由名称及若干括号之内的模式构成。如BinOp("+" , e , Number(0))。

序列模式:可以像匹配样本类那样匹配List或Array这样的序列类型。同样的语法现在可以指定模式内任意数量的元素。如:

1 expr match{
2 case List(0 , _ , _ ) => println("found it")
3 case _ =>
4 }
   清单  15.8

  如果想匹配一个不指定长度的序列,可以指定_*作为模式的最后元素。它能匹配序列中0到任意数量的元素。

元组模式:例子:

1 def tupleDemo(expr : Any) = 
2 expr match {
3 case (a , b, c) => println("matched " + a + b + c)
4 case _ =>
5 }
清单 15.9

类型模式:可以把它当做类型测试和类型转换的简易替代。例如:

1 def generalSize(x : Any) = x match{
2 case s : String => s.length
3 case m : Map[_ , _] => m.size
4 case _ => 1
5 }
清单 15.11

使用: scala> generalSize(Map(1 -> 'a' , 2 -> 'b'))

    res15 : Int = 2

另:在Scala里类型测试和转换的代码很冗长,因为不建议这么做。

 

模式守卫:模式变量仅允许在模式中出现一次。如:

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

  这种写法就会出错。可以改成:  case BinOp("+" , x , y ) if x == y => BinOp("*" , x , Number(2))

  模式守卫接在模式之后,开始于if。守卫可以是任意的引用模式中变量的布尔表达式。如果存在模式守卫,那么只有在守卫返回true的时候匹配才成功。



 

  

转载于:https://www.cnblogs.com/peterzd/archive/2011/11/14/2243772.html

相关文章:

  • mencoder视频旋转
  • 314亿美元拿下ARM,为什么说软银是捡便宜?
  • 【翻译】EF 4.2 Model Database First演示
  • 颜值担当 金羚洗衣机引领新时尚
  • 降水如何转为资源?下水道体现城市智慧
  • Const and volatile的区别和简介(英文版的)
  • 针对美国联邦机构的NIST网络框架将出台
  • [linux学习]apt-get参数解析
  • 我们工作到底为了什么?
  • 标签概述及GoodMES云标签的创新应用
  • 勒索病毒卷土重来!目标对准安卓机伪装身份诱惑人
  • 程序员一次跳槽失败的经历[转]
  • 业内新声音 黑客将在网络安全中获得新角色
  • FreeBSD上Enter full pathname of shell or RETURN for /bin/sh 问题的解决
  • 【JAVA基础】HashSet、LinkedHashSet、TreeSet使用区别
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • dva中组件的懒加载
  • JSONP原理
  • JS基础之数据类型、对象、原型、原型链、继承
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • overflow: hidden IE7无效
  • 搭建gitbook 和 访问权限认证
  • 复杂数据处理
  • 构造函数(constructor)与原型链(prototype)关系
  • 浏览器缓存机制分析
  • 批量截取pdf文件
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • # C++之functional库用法整理
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (C++17) optional的使用
  • (Python) SOAP Web Service (HTTP POST)
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (分布式缓存)Redis持久化
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (自适应手机端)响应式服装服饰外贸企业网站模板
  • .bat批处理(六):替换字符串中匹配的子串
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • /bin、/sbin、/usr/bin、/usr/sbin
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @Async注解的坑,小心
  • @Bean注解详解
  • @Controller和@RestController的区别?
  • [ C++ ] STL---string类的模拟实现
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [20150321]索引空块的问题.txt
  • [BZOJ5250][九省联考2018]秘密袭击(DP)
  • [C#]C# OpenVINO部署yolov8图像分类模型