推荐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函数的定义,看到的是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方法的匹配,然后一切又可以按照固有的思维去看。
Scala的模式匹配本质是什么? -从Coursera的响应式编程说起