abstract class JSON case class JSeq(elems: List[JSON]) extends JSON case class JObj(bindings: Map[String, 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
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("211 555-1234")
)),
JObj(Map(
"type" -> JStr("fax"), "number" -> JStr("646 555-4567")
))
))
))
def show(json: JSON): String = json match { case JSeq(elems) => "[" + (elems map show mkString ", ") + "]" case JObj(bindings) => val assocs = bindings.map { case (key, value) => "\"" + key + "\": " + show(value) } "{" + (assocs mkString ", ") + "}" case JNum(num) => num.toString case JStr(str) => '\"' + str + '\"' case JBool(b) => b.toString case JNull => "null" }
{
"firstName": "John",
"lastName": "Smith",
"address": {
"streetAddress": "21 2nd street",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
{
"type": "home",
"number": "211 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
需要值得我们深思的是这一段:
这段代码本身,不是一个类型。
打开map函数的定义,看到的是map[B, That](f: A => B),意思是,输入时A,给出B。
对于上面的map,它期望得到的输入应当是JBinding(我们定义type JBinding = (String, JSON)),输出String;也就是JBinding => String
我们再看看=>这个符号,这其实就是一个函数的表示 A=>B就是一个函数。其实这样A=》B的格式是scala的Function1的简写。那么上面的JBinding => String,就是scala.Function1[JBinding, String]
继续看trait Function1的定义(apply方法,天堂的入口)。
trait Function1[-A, +R] {
def apply(x: A): R
}
在做模式匹配的过程中,{ case (key, value) => "\"" + key + "\": " + show(value) } 被翻译成
new Function1[JBinding, String] {
def apply(x: JBinding) = x match {
case (key, value) => key + ";" + show(value)
}
}
然后大家都能看懂了吧?
最后总结一下: scala的语法中,所有模式匹配最后都归结到apply方法的匹配,然后一切又可以按照固有的思维去看。