scala 模式匹配详解 2 scala里是怎么实现的?
在这篇martin和另外两位模式匹配领域专家的论文里说了模式匹配的几种实现方式,以及scala是选择哪种方式来实现的。
http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
我引用了里面的一些描述。
在面向对象的程序中数据被组织为一级一级的类(class)
面向对象语言在模式匹配方面的问题在于如何从外部探测这个层级。
有6种实现模式匹配的方法:
1) 面向对象的分解 (decomposition)
2) 访问器模式 (visitor)
3) 类型测试/类型造型 (type-test/type-cast)
4) typecase
5) 样本类 (case class)
6) 抽取器 (extractor)
论文里从3个维度9个标准来对比了各种实现方式:
简明程度(框架支持、浅匹配、深匹配),维护性(表征独立、扩展性),性能(基础性能、广度和深度延展性)
比较的细节在这篇论文里有提,不一一展开。
最终scala选择了采用 样本类(case class) 和 抽取器(extractor) 来实现模式匹配。
我们大致了解一下case class和extractor 是怎么回事
1)样本类(case class)
本质上case class是个语法糖,对你的类构造参数增加了getter访问,还有toString, hashCode, equals 等方法;
最重要的是帮你实现了一个伴生对象,这个伴生对象里定义了apply 方法和 unapply 方法。
apply方法是用于在构造对象时,减少new关键字;而unapply方法则是为模式匹配所服务。
这两个方法可以看做两个相反的行为,apply是构造(工厂模式),unapply是分解(解构模式)。
case class在暴露了它的构造方式,所以要注意应用场景:当我们想要把某个类型暴露给客户,但又想要隐藏其数据表征时不适宜。
2) 抽取器(extrator)
抽取器是指定义了unapply方法的object。在进行模式匹配的时候会调用该方法。
unapply方法接受一个数据类型,返回另一数据类型,表示可以把入参的数据解构为返回的数据。
比如
class A
class B(val a:A)
object TT {
def unapply(b:B) = Some(new A)
}
这样定义了抽取器TT后,看看模式匹配:val b = new B(new A); b match{ case TT(a) => println(a) }
直观上以为 要拿b和TT类型匹配,实际被翻译为 TT.unapply(b) match{ case Some(…) => … }
它与上面的case class相比,相当于自己手动实现unapply,这也带来了灵活性。
后续会专门介绍一下extrator,这里先看一下extractor怎么实现case class无法实现的”表征独立”(representation independence)
比如我们想要暴露的类型为A
//定义为抽象类型
trait A
//然后再实现一个具体的子类,有2个构造参数
class B (val p1:String, val p2:String) extends A
//定义一个抽取器
object MM{
//抽取器中apply方法是可选的,这里是为了方便构造A的实例
def apply(p1:String, p2:String) : A = new B(p1,p2);
//把A分解为(String,String)
def unapply(a:A) : Option[(String, String)] = {
if (a.isInstanceOf[B]) {
val b = a.asInstanceOf[B]
return Some(b.p1, b.p2)
}
None
}
}
这样客户只需要通过 MM(x,y) 来构造和模式匹配了。客户只需要和MM这个工厂/解构角色打交道,A的实现怎么改变都不受影响。
注:
有很多的资料里在介绍case class时经常把它和函数式语言里的代数数据类对比(ADT)
严格的说Scala中的case class并不是ADT,但比较靠近,可以模拟ADT。
这篇文章中提到case class介于类继承和代数数据类型之间 http://blog.csdn.net/jinxfei/article/details/4677359
提到:”Scala则提供了一种介于两者之间(类继承和代数数据类型),被称为条件类(case classes)的概念”
《Programming in Scala》中文版,在术语表中有提到ADT:
通过提供若干个含有独立构造器的备选项(alternative)来定义的类型。通常可以辅助于通过模式匹配解构类型的方式。
这个概念可以在规约语言和函数式语言中发现。代数数据类型在Scala中可以用样本类(case class)模拟。
转自:http://ifeve.com/pattern-matching-2/
scala 模式匹配详解 2 scala里是怎么实现的?的更多相关文章
- scala 模式匹配详解 1
什么是模式? 一些刚从java转到scala的同学在开发的过程中犹如深陷沼泽,因为很多的概念或风格不确定,scala里有很多的坑,模式匹配也算一个.我整理了一下自己所理解的概念,以及一些例子.这个系列 ...
- scala 模式匹配详解 3 模式匹配的核心功能是解构
http://www.artima.com/scalazine/articles/pattern_matching.html这篇文章是odersky谈scala中的模式匹配的一段对话,我做了部分片段翻 ...
- Scala 入门详解
Scala 入门详解 基本语法 Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的 Scala 程序是对象的集合,通过调用彼此的方法来实现消息传递.类,对象,方法,实例变 ...
- KMP字符串模式匹配详解(zz)
刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN A_B_ ...
- KMP字符串模式匹配详解
KMP字符串模式匹配详解 http://www.cppblog.com/oosky/archive/2006/07/06/9486.html
- Spark入门到精通--(第二节)Scala编程详解基础语法
Scala是什么? Scala是以实现scaleable language为初衷设计出来的一门语言.官方中,称它是object-oriented language和functional languag ...
- Scala入门详解
object作为Scala中的一个关键字,相当于Java中的public static class这样的一个修饰符,也就说object中的成员都是静态的! 所以我们在这个例子中的main方法是静态的, ...
- Scala集合类详解
对scala中的集合类虽然有使用,但是一直处于一知半解的状态.尤其是与java中各种集合类的混合使用,虽然用过很多次,但是一直也没有做比较深入的了解与分析.正好趁着最近项目的需要,加上稍微有点时间,特 ...
- Scala面向对象详解
Scala的包(作用域) package com.jh.scala 等同于 package jh \n package scala 等同于 package com.jh{ package scala ...
随机推荐
- Makefile 中的.PHONY
PHONY 目标并非实际的文件名:只是在显式请求时执行命令的名字.有两种理由需要使用PHONY 目标:避免和同名文件冲突,改善性能. 所谓的PHONY这个单词就是伪造的意思,makefile中将.PH ...
- Gradle Build Tool
转自知乎: nonesuccess 通俗的说:gradle是打包用的. 你觉得解决你的问题了吗?如果没解决,那是你的问题提得不够好.比如我猜你应该提:为什么要打包发布,打包发布有几种常见方法,为什么这 ...
- 各hbase版本对hadoop各版本的支持情况
http://hbase.apache.org/book/configuration.html#basic.prerequisites HBase-0.94.x HBase-0.98.x (Sup ...
- Spark机器学习(11):协同过滤算法
协同过滤(Collaborative Filtering,CF)算法是一种常用的推荐算法,它的思想就是找出相似的用户或产品,向用户推荐相似的物品,或者把物品推荐给相似的用户.怎样评价用户对商品的偏好? ...
- 《Unix&Linux大学教程》学习笔记6——Unix文件系统
1:Unix文件类型——3种 普通文件(常规文件):文本文件(纯文本.脚本.源程序.配置文件.html等).二进制文件(多媒体文件.数据库等) 目录:用于组织文件 伪文件:不存储数据,目的是提供一种服 ...
- 用MATLAB生成模糊控制离线查询表
实时采样得到的数据经过模糊化处理后输入机器,通过查询模糊规则表便可得到应有的输出模糊量,从而避免了近似推理过程.实际应用中,特别是在控制系统较为简单而采用单片机控制时,常常采用这种查表法. 模糊控制表 ...
- Linux下的两种磁盘分区工具的使用
如何使用fdisk和parted分区工具来进行硬盘分区,下面我来说一下在Linux系统中这两种硬盘分区工具的使用方法: ----------fdisk分区工具---------- ...
- 一张图作为Python入门(图片来自网络)
- C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法
C#调用接口注意要点 在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...
- linux内核剖析(零)linux系统启动过程详解-开机加电后发生了什么
本文参考了如下文章 深入理解linux启动过程 mbr (主引导记录(Master Boot Record)) 电脑从开机加电到操作系统main函数之前执行的过程 详解linux系统的启动过程及系统初 ...