Scala的模式匹配的思考
##Scala的模式匹配本质是什么?
推荐Coursera上的响应式编程课程,这个课程是scala语言的进阶课程。
课程的开始提出了这样一个应用场景:构建Json串,不知道Json的同学随便google一下。 为了做到这些事情,我们定义了下面的一些类
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
接着,我们构建一个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")
))
))
))
然后把Json显示出来
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"
}
]
}
#需要值得我们深思的是这一段:
{ case (key, value) => "\"" + key + "\": " + show(value) }
{case (key, value) => "\"" + key + "\": " + show(value)}
到底是什么类型? 这段代码是怎么跟前面的map结合起来的? 这段代码本身,不是一个类型。
打开map函数的定义,看到的是mapB, That,意思是,输入时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方法的匹配,然后一切又可以按照固有的思维去看。