我是Scala的新手,試圖理解模式匹配結構的語法,特別是來自Unfiltered(http://unfiltered.databinder.net/Try+Unfiltered.html)中的示例。Scala/Unfiltered中的模式匹配語法
這是一個簡單的HTTP服務器,可以回顯Hello World!和2份的路徑,如果該路徑是2份長:
package com.hello
import unfiltered.request.GET
import unfiltered.request.Path
import unfiltered.request.Seg
import unfiltered.response.ResponseString
object HelloWorld {
val sayhello = unfiltered.netty.cycle.Planify {
case GET(Path(Seg(p :: q :: Nil))) => {
ResponseString("Hello World! " + p + " " + q);
}
};
def main(args: Array[String]) {
unfiltered.netty.Http(10000).plan(sayhello).run();
}
}
同樣爲了參考的路徑,波段的源代碼,和GET /方法對象:
package unfiltered.request
object Path {
def unapply[T](req: HttpRequest[T]) = Some(req.uri.split('?')(0))
def apply[T](req: HttpRequest[T]) = req.uri.split('?')(0)
}
object Seg {
def unapply(path: String): Option[List[String]] = path.split("/").toList match {
case "" :: rest => Some(rest) // skip a leading slash
case all => Some(all)
}
}
class Method(method: String) {
def unapply[T](req: HttpRequest[T]) =
if (req.method.equalsIgnoreCase(method)) Some(req)
else None
}
object GET extends Method("GET")
我能夠打破怎樣大部分工作,但此行讓我百思不得其解:
case GET(Path(Seg(p :: q :: Nil))) => {
我理解代碼的目的,但這樣做的不是如何應用。我非常有興趣瞭解Scala的各種細節,而不是簡單地使用它來實現一個HTTP服務器,所以我一直在深入研究它幾個小時。我明白,這事做對了GET
,Path
和Seg
對象提取和unapply
方法,我也知道,當我調試它擊中在GET
unapply
Seg
之前Path
和Path
之前。
我不明白下面的事情:
爲什麼我不能寫
GET.unapply(req)
,但我可以寫GET(req)
或GET()
,它會匹配任何HTTP GET?爲什麼編譯器知道什麼值會傳遞給每個提取器的
unapply
方法?看起來它會將它們鏈接在一起,除非其中一個返回None
而不是Some
?它如何綁定變量p和q?它知道它們是字符串,它必須從返回類型
Seg.unapply
推斷出來,但我不明白將p分配給列表第一部分的值的機制,以及q列表的第二部分的值。有沒有辦法改寫它,使其更清楚發生了什麼?當我第一次看到這個例子時,我被
val sayhello = unfiltered.netty.cycle.Planify {
弄糊塗了,我找到並重寫了它,發現它隱式地創建了一個PartialFunction並將它傳遞給了Planify.apply。