现在的位置: 首页 > 综合 > 正文

scala学习八 模式匹配之领域语言

2019年05月24日 ⁄ 综合 ⁄ 共 1529字 ⁄ 字号 评论关闭

计算器DSL的设计:

根据那些基本的编译理论中最精华的部分,您可以得知一个语言处理器(包括解释器和编译器)的基本运算至少由两个阶段组成:

  • 解析器,用于获取输入的文本并将其转换成 Abstract Syntax Tree(AST)抽象语法树。
  • 代码生成器(在编译器的情况下),用于获取 AST 并从中生成所需字节码;或是求值器(在解释器的情况下),用于获取 AST 并计算它在 AST 里面所发现的内容。

scala中的case类这很适合用来构建AST:

什么是case类( 是通过工程方法发创建的):

package caseclass
case class Person(first: String, last: String, age: Int) <span style="background-color: rgb(255, 255, 255);">{
  println(first);
  println(last)
  println(age)
}</span>

object App {
  def main(args: Array[String]): Unit =
    {
      val ted = Person("Ted", "Neward", 37)
      val amanda = Person("Amanda", "Laucher", 27)

      System.out.println(process(ted))
      System.out.println(process(amanda))
    }

  def process(p: Person) =
    {
      "Processing " + p + " reveals that" +
        (p match {
          <span style="background-color: rgb(192, 192, 192);">case Person(_, _, a) if a > 30 =>
            " they're certainly old."
          case Person(_, "Neward", _) =>
            " they come from good genes...."
          case Person(first, last, ageInYears) if ageInYears > 17 =>
            first + " " + last + " is " + ageInYears + " years old."
          case _ =>
            " I have no idea what to do with this person"</span>
        })
    }
}

第一个 case 表达式里面有两个通配符(带下划线的字符就是通配符),这意味着该匹配将会为符合匹配的 Person 中那两个字段获取任何值,但是它引入了一个局部变量 ap.age 中的值会绑定在这个局部变量上。这个
case 只有在同时提供的起保护作用的表达式(跟在它后边的 
if 表达式)成功时才会成功,
但只有第一个 
Person 会这样,第二个就不会了。第二个 case 表达式
在 
Person 的 firstName 部分使用了一个通配符,但在 lastName 部分使用常量字符串 Neward 来匹配,在 age 部分使用通配符来匹配。

由于第一个 Person 已经通过前面的 case 匹配了,而且第二个 Person 没有姓 Neward,所以该匹配不会
为任何一个 Person 而被触发(但是,Person("Michael",
"Neward", 15)
 会由于第一个 case 中的 guard 子句失败而转到第二个 case)。

第三个示例展示了模式匹配的一个常见用途,有时称之为提取,在这个提取过程中,匹配对象 p 中的值为了能够在
case 块内使用而被提取到局部变量中(第一个、最后一个和 ageInYears)。最后的
case 表达式是普通 case 的默认值,它只有在其他 case 表达式均未成功的情况下才会被触发。

简要了解了 case 类和模式匹配之后,接下来让我们回到创建计算器 AST 的任务上。

抱歉!评论已关闭.