《programming in scala》2ed chap15学习笔记

package chap15

sealed abstract class Expr // 加了sealed,其他文件里不能extends Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr

object Chap15 {
  def main(args: Array[String]) {
    case class XXExpr extends Expr // 在同一file的 不同地方可以extends sealed class

    /*
   * case class有几个好处
   */
    // 1. factory method
    val expr = BinOp("+", Number(1), Var("x"))
    // 2. get val prefix
    val num = expr.left
    // 3. structural toString, hashCode, equals
    println(expr.right == Var("x")) // true
    // 4. copy method
    val expr2 = expr.copy("-")
    val expr3 = expr.copy(left = Number(2))
    println(expr2, expr3)

    /*
     * 15.2 kinds of patterns
     */
    // 1. wildcard patterns
    val exprStr = expr match {
      case BinOp("+", a, b) =>
        println(a, b); a
      case _ => // 什么都不需要写,()
    }
    println(exprStr)
    // 2. constant patterns
    def describe(x: Any) = x match {
      case 5 => "five"
      case true => "truth"
      case "hello" => "hi!"
      case Nil => "the empty list"
      case _ => "something else"
    }
    // 3. Variable patterns
    /* matches any object, just like a wildcard, 有名字可以引用
     * a simple name starting with a lowercase letter is taken to be a pattern variable; 
     * all other references are taken to be constants.
     */
    val Pi = 3.14
    val E = 2.71
    val pi = Pi //> pi  : Double = 3.14
    E match {
      case Pi => "strange?!"
      case _ => "Ok"
    }
    E match {
      case pi => "strange?!"
      case _ => "Ok"
    }
    E match {
      case `pi` => "strange?!"
      case _ => "Ok"
    }

    // 4. Constructor patterns, deep matches
    // 5. Sequence patterns
    expr match {
      case List(0, _, _*) => println("found it")
      case _ =>
    }
    // 6. Tuple patterns
    def tupleDemo(expr: Any) =
      expr match {
        case (a, b, c) => println("matched " + a + b + c)
        case _ =>
      }
    // 7. Typed patterns
    /*
     * 比expr.isInstanceOf[String]然后expr.asInstanceOf[String]好
     */
    def generalSize(x: Any) = x match {
      case s: String => s.length
      case m: Map[_, _] => m.size
      case _ => -1
    }
    println(generalSize(null: String)) // it matches every (non-null) instance of String. 

    val typedValue: Any = List("a", "b") //> typedValue  : Any = List(a, b)
    val typed = typedValue match {
      case s: List[_] => s.length // List[Int]或者List[String]都没有用,type erasure
      case _ => 1
    } //> typed  : Int = 2

    val typedValueArr: Any = Array("a", "b", "c") //> typedValueArr  : Any = Array(a, b, c)
    // val typedValueArr: Any = Array(1, 2, 3)
    val typedArr = typedValueArr match {
      case s: Array[Int] => s.length // The element type of an array is stored with the array value, so you can pattern match on it
      case _ => 1
    }
    // 8.Variable binding
    val expr4: Expr = expr
    expr4 match {
      case UnOp("abs", e @ UnOp("abs", _)) => e
      case _ =>
    }

    // 15.3 Pattern guards
    def simplifyAdd(e: Expr) = e match {
      case BinOp("+", x, y) if x == y => // 不能用BinOp("+", x, x),Scala restricts patterns to be linear: a pattern variable may only appear once in a pattern.
        BinOp("*", x, Number(2))
      case _ => e
    }

    // 15.4 Pattern overlaps
    /*
     * it is important that the catch-all cases come after the 
     * more specific simplification rules.
     */

    // 15.5 Sealed classes
    def describe2(e: Expr): String = (e: @unchecked) match { //sealed帮助编译检查,没有@unchecked会有编译warning
      case Number(_) => "a number"
      case Var(_) => "a variable"
    }

    // 15.7 Patterns everywhere
    // 1. variable definitions
    val myTuple = (123, "abc")
    val (number, string) = myTuple
    // 2. Case sequences as partial functions
    // If the declared type is just Function1, or is missing,
    // the function literal is instead translated to a complete function.
    val second: PartialFunction[List[Int], Int] = { // List[Int] => Int会有warning
      case x :: y :: _ => y
    }
    println(second.isDefinedAt(List(5)))
    /*
     * In fact, such an expression gets translated by the Scala compiler to a partial function 
     * by translating the patterns twice
     */
    val second2 = new PartialFunction[List[Int], Int] {
      def apply(xs: List[Int]) = xs match {
        case x :: y :: _ => y
      }
      def isDefinedAt(xs: List[Int]) = xs match {
        case x :: y :: _ => true
        case _ => false
      }
    }
    println(second2.isDefinedAt(List(5, 6)))
    println(second2(List(5, 6, 7)))
    // 3. Patterns in for expressions
    val results = List(Some("apple"), None, Some("orange"))
    for (Some(x) <- results) println(x) // 不会有None, generated values that do not match the pattern are discarded. F
  }
}


你可能感兴趣的:(scala,case,Pattern,Class,matching)