zoukankan      html  css  js  c++  java
  • scala模式匹配与样例类

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

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

        3.编译器为这个类添加了方法toString,hashCode和equals等方法。

    模式匹配:

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

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

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

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

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

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------

    代码示例:

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /* 
    2. desc:模拟控制数学表达式的库。 
    3.       由变量、数字、一元及二元操作符组成的数学表达式。 
    4.       jb,完全照书上的来说。 
    5. */  
    6.   
    7. object simpleBegin {  
    8.     def main(args: Array[String]): Unit = {  
    9.         //--x  
    10.         println(simplifyTop(UnOp("-", UnOp("-", Var("x")))))  
    11.         //x+0  
    12.         println(simplifyTop(BinOp("+", Var("x"), Number(0))))  
    13.         //x*1  
    14.         println(simplifyTop(BinOp("*", Var("x"), Number(1))))  
    15.         //abs abs x  
    16.         println(simplifyTop(UnOp("abs", UnOp("abs", Var("x")))))  
    17.         
    18.     }  
    19.   
    20.     //层级包括一个抽象基类Expr和四个子类,每个代表一种表达式。所有的五个类都没有结构体。  
    21.     //class C 和 class C {} 一个意思。  
    22.     abstract class Expr  
    23.     case class Var(name: String) extends Expr  
    24.     case class Number(num: Double) extends Expr  
    25.     case class UnOp(operator: String, arg: Expr) extends Expr  
    26.     case class BinOp(operator: String, left: Expr, right: Expr) extends Expr  
    27.   
    28.     //“e“是什么意思????变量模式!  
    29.     //tips: case BinOp("*", e, Number(1)) => e 可以写成: case BinOp(a, e, b) => e !!!!!!!!!!!!!  
    30.     def simplifyTop(expr: Expr): Expr = expr match{  
    31.         case UnOp("-", UnOp("-", e)) => e  
    32.         case BinOp("+", e, Number(0)) => e  
    33.         case BinOp("*", e, Number(1)) => e  
    34.         //变量绑定,规则:变量 @ 模式,此时“变量”就代表了后面的“模式”:Unop("abs", _)  
    35.         case UnOp("abs", x @ UnOp("abs", _)) => x  
    36.     }     
    37.       
    38. }  

    -------------------------------------------------------------------------------------------------------------------------------------------------------------

    输出结果:

    Var(x)
    Var(x)
    Var(x)
    UnOp(abs,Var(x))

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    模式的种类

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

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

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

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. expr match{  
    2.   case 0 => "zero"  
    3.   case somethingElse => "not zero" + somethingElse  
    4. }         

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

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

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

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. expr match{  
    2.    case List(0 , _ , _ ) => println("found it")  
    3.    case _ =>   
    4.  }  

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

    元组模式:例子:

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. def tupleDemo(expr : Any) =   
    2.   expr match {  
    3.     case (a , b, c) => println("matched " + a + b + c)  
    4.     case _ =>   
    5.   }  

     

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

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. def generalSize(x : Any) = x match{  
    2.   case s : String => s.length  
    3.   case m : Map[_ , _] => m.size  
    4.   case _ => 1  
    5. }  

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

        res15 : Int = 2

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

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. case BinOp("+" , x , x ) => BinOp("*" , x , Number(2))  

     

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

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

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

  • 相关阅读:
    python,生产环境安装
    neo4j 图数据库
    RNN系列
    机器学习关于AUC的理解整理
    fensorflow 安装报错 DEPENDENCY ERROR
    dubbo Failed to check the status of the service com.user.service.UserService. No provider available for the service
    使用hbase遇到的问题
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk
    gradle 安装
    jenkins 安装遇到的坑
  • 原文地址:https://www.cnblogs.com/Evil-Rebe/p/5793422.html
Copyright © 2011-2022 走看看