1. 用scala 表示JSON数据

package week1

abstract class JSON 
case class JObj(bindings: Map[String, JSON]) extends JSON 
case class JSeq(elems: List[JSON]) extends JSON
case class JNum(num: Double) extends JSON
case class JStr(str: String) extends JSON
case class JBool(b: Boolean) extends JSON
case object JNull extends JSON

将JSON对象显示为JSON串

package week1

object Main extends App {

  val data = JObj(Map(
    "firstName" -> JStr("John"),
    "lastName" -> JStr("Smith"),
    "address" -> JObj(Map(
      "streetAddress" -> JStr("21 2nd Street"),
      "state" -> JStr("NY"),
      "postalCode" -> JNum(10021))),
    "phoneNumbers" -> JSeq(List(
      JObj(Map(
        "type" -> JStr("home"), "number" -> JStr("212 555-1234"))),
      JObj(Map(
        "type" -> JStr("fax"), "number" -> JStr("646 555-4567")))))))

  def show(json: JSON): String = json match {
    case JNum(num) => num.toString
    case JBool(b) => b.toString
    case JNull => "null"
    case JStr(str) => '\"' + str + '\"'
    case JSeq(elems) => "[" + (elems map show mkString ",") + "]"
    case JObj(bindings) => 
      val assoc = bindings map {
        case (key, value) => "\""+key+"\""+":"+"\""+show(value)+"\""
      }
      "{"+ ( assoc mkString ",") + "}"
  }
  println(show(data))
}


2. case 序列作为函数:只有提供函数签名信息,编译器能自动将函数定义补全

  val f:String => String = {case "ping" => "pong"}//> f  : String => String = <function1>
  f("ping")                                       //> res0: String = pong
  // f的定义等价于
  val ff = new Function1[String, String] {
     def apply(s: String) = s match {
       case "ping" => "pong"
     }
  }                                               //> ff  : String => String = <function1>

 

但是f有可能抛mactch error

package week1

object Test {
  val f:String => String = {case "ping" => "pong"}//> f  : String => String = <function1>
  f("ping")                                       //> res0: String = pong
  f("pong")                                       //> scala.MatchError: pong (of class java.lang.String)
                                                  //| 	at week1.Test$$anonfun$main$1$$anonfun$1.apply(week1.Test.scala:4)
                                                  //| 	at week1.Test$$anonfun$main$1$$anonfun$1.apply(week1.Test.scala:4)
                                                  //| 	at week1.Test$$anonfun$main$1.apply$mcV$sp(week1.Test.scala:6)
                                                  //| 	at org.scalaide.worksheet.runtime.library.WorksheetSupport$$anonfun$$exe
                                                  //| cute$1.apply$mcV$sp(WorksheetSupport.scala:76)
                                                  //| 	at org.scalaide.worksheet.runtime.library.WorksheetSupport$.redirected(W
                                                  //| orksheetSupport.scala:65)
                                                  //| 	at org.scalaide.worksheet.runtime.library.WorksheetSupport$.$execute(Wor
                                                  //| ksheetSupport.scala:75)
                                                  //| 	at week1.Test$.main(week1.Test.scala:3)
                                                  //| 	at week1.Test.main(week1.Test.scala)
}

这时可以用偏函数,在调用前检查一下在参数处是否有定义

package week1

object Test {
  val f:PartialFunction[String, String] = {case "ping" => "pong"}
                                                  //> f  : PartialFunction[String,String] = <function1>
  f.isDefinedAt("ping")                           //> res0: Boolean = true
  f.isDefinedAt("pong")                           //> res1: Boolean = false
}

偏函数的定义如下:

trait PartialFunction[-A, +R] extends Function1[-A, +R] {
def apply(x: A): R
def isDefinedAt(x: A): Boolean
}

它继承了Function1,添加了isDefinedAt方法


3.但是检查isDefinedAt并不能保证不抛MatchError

  val g: PartialFunction[List[Int], String] = {
    case Nil => "one"
    case x :: rest =>
      rest match {
        case Nil => "two"
      }
  }
  g.isDefinedAt(List(1, 2, 3))  //true