清单 这不是以前的类
object App{def main(args : Array[String]) : Unit ={val ted = Person( Ted Neward )val ted = Person( Ted Neward )val amanda = Person( Amanda Laucher )System out println( ted == amanda: +(if (ted == amanda) Yes else No ))System out println( ted == ted: +(if (ted == ted) Yes else No ))System out println( ted == ted : +(if (ted == ted ) Yes else No ))}}/*C:\Projects\Exploration\Scalascala Appted == amanda: Noted == ted: Yested == ted : Yes*/
case 类的真正价值体现在模式匹配中 本系列的读者可以回顾一下模式匹配(参见 本系列的第二篇文章 关于 Scala 中的各种控制构造) 模式匹配类似 Java 的 switch/case 只不过它的本领和功能更加强大 模式匹配不仅能够检查匹配构造的值 从而执行值匹配 还可以针对局部通配符(类似局部 默认值 的东西)匹配值 case 还可以包括对测试匹配的保护 来自匹配标准的值还可以绑定于局部变量 甚至符合匹配标准的类型本身也可以进行匹配
有了 case 类 模式匹配具备了更强大的功能 如清单 所示
清单 这也不是以前的 switch
case class Person(first:String last:String age:Int);object App{def main(args : Array[String]) : Unit ={val ted = Person( Ted Neward )val amanda = Person( Amanda Laucher )System out println(process(ted))System out println(process(amanda))}def process(p : Person) ={Processing + p + reveals that +(p match{case Person(_ _ a) if a=they re certainly oldcase Person(_ Neward _) =they e from good genescase Person(first last ageInYears) if ageInYears=first + + last + is + ageInYears + years oldcase _ =I have no idea what to do with this person})}}/*C:\Projects\Exploration\Scalascala AppProcessing Person(Ted Neward ) reveals that they re certainly old Processing Person(Amanda Laucher ) reveals that Amanda Laucher is years old */
清单 中发生了很多操作 下面就让我们先慢慢了解发生了什么 然后回到计算器 看看如何应用它们
首先 整个 match 表达式被包裹在圆括号中 这并非模式匹配语法的要求 但之所以会这样是因为我把模式匹配表达式的结果根据其前面的前缀串联了起来(切记 函数性语言里面的任何东西都是一个表达式)
其次 第一个 case 表达式里面有两个通配符(带下划线的字符就是通配符) 这意味着该匹配将会为符合匹配的 Person 中那两个字段获取任何值 但是它引入了一个局部变量 a p age 中的值会绑定在这个局部变量上 这个 case 只有在同时提供的起保护作用的表达式(跟在它后边的 if 表达式)成功时才会成功 但只有第一个 Person 会这样 第二个就不会了 第二个 case 表达式在 Person 的 firstName 部分使用了一个通配符 但在 lastName 部分使用常量字符串 Neward 来匹配 在 age 部分使用通配符来匹配
由于第一个 Person 已经通过前面的 case 匹配了 而且第二个 Person 没有姓 Neward 所以该匹配不会为任何一个 Person 而被触发(但是 Person( Michael Neward ) 会由于第一个 case 中的 guard 子句失败而转到第二个 case)
第三个示例展示了模式匹配的一个常见用途 有时称之为提取 在这个提取过程中 匹配对象 p 中的值为了能够在 case 块内使用而被提取到局部变量中(第一个 最后一个和 ageInYears) 最后的 case 表达式是普通 case 的默认值 它只有在其他 case 表达式均未成功的情况下才会被触发
简要了解了 case 类和模式匹配之后 接下来让我们回到创建计算器 AST 的任务上
计算器 AST
首先 计算器的 AST 一定要有一个公用基类型 因为数学表达式通常都由子表达式组成 通过 + ( * ) 就可以很容易地看到这一点 在这个例子中 子表达式 ( * ) 将会是 + 运算的右侧运算数
事实上 这个表达式提供了三种 AST 类型
●基表达式●承载常量值的 Number 类型●承载运算和两个运算数的 BinaryOperator
- mysql游标和存储过程是什么 mysql游标表名为变量
- mysql子查询和连接查询 mysql子查询插入
- 纯phpmysql
- mongodb存储图片和文件实践 mongodb存文件和表
- java查询数组中是否包含某一个值 javamongodb数组查询
- 数据库和redis数据不一致 h2数据库和redis
- mongodb 权威指南 mongodb权威指南和实战
- mongo 新建数据库 mongodb创建用户和数据库
- redis怎么和数据库交互 redis数据结合
- redis实战电子书 redisjava书籍
