我是 Scala 的新手,并试图理解模式匹配构造的语法,特别是来自 Unfiltered ( http://unfiltered.databinder.net/Try+Unfiltered.html ) 中的示例。
这是一个简单的 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();
}
}
还可以参考 Path、Seg 和 GET/Method 对象的源代码:
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 服务器,所以我已经研究了几个小时。我知道它与提取器和, 和对象上的unapply
方法有关GET
,我也知道当我调试它时会遇到before和before 。Path
Seg
unapply
GET
Path
Path
Seg
我不明白以下几点:
为什么我不能写
GET.unapply(req)
,但我可以写GET(req)
或者GET()
它会匹配任何HTTP GET?编译器为什么或如何知道将哪些值传递给每个提取器的
unapply
方法?似乎它只会将它们链接在一起,除非其中一个返回 aNone
而不是Some
?它如何绑定变量 p 和 q?它知道它们是字符串,它必须从 的返回类型推断出来
Seg.unapply
,但我不明白分配 p 列表第一部分的值和 q 列表第二部分的值的机制。有没有办法重写它以使其更清楚发生了什么?当我第一次看这个例子的时候,我被这行弄糊涂了
val sayhello = unfiltered.netty.cycle.Planify {
,我翻来覆去重写了它,发现它隐式地创建了一个 PartialFunction 并将它传递给 Planify.apply。