首页 > 代码库 > Scala的模式匹配本质是什么? -从Coursera的响应式编程说起

Scala的模式匹配本质是什么? -从Coursera的响应式编程说起

推荐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 = http://www.mamicode.com/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方法的匹配,然后一切又可以按照固有的思维去看。