私は Scala を初めて使用し、特に Unfiltered ( http://unfiltered.databinder.net/Try+Unfiltered.html ) の例から、パターン マッチング構造の構文を理解しようとしています。
Hello World! をエコー バックする単純な HTTP サーバーを次に示します。パスが 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))) => {
コードの目的は理解できますが、それがどのように適用されるかはわかりません。私は単に HTTP サーバーを実装するのではなく、Scala の詳細を学ぶことに非常に興味があるので、これについて数時間掘り下げてきました。、、およびオブジェクトのエクストラクタとunapply
メソッドに関係があることを理解しています。また、デバッグするとbeforeとbeforeにヒットすることも知っています。GET
Path
Seg
unapply
GET
Path
Path
Seg
次のことがわかりません。
なぜ私は書くことができないのに、 or
GET.unapply(req)
を書くことができ、どの HTTP GET とも一致するのでしょうか?GET(req)
GET()
unapply
コンパイラは、各エクストラクタのメソッドに渡される値をなぜ、またはどのように知るのでしょうか? どちらかが?のNone
代わりにa を返さない限り、それらを連鎖させるだけのようです。Some
変数 p と q をどのようにバインドしますか? それらが文字列であることはわかっています。戻り値の型からそれを推測する必要があり
Seg.unapply
ますが、リストの最初の部分の値を p に、リストの 2 番目の部分の値を q に割り当てるメカニズムがわかりません。何が起こっているのかをより明確にするために書き直す方法はありますか?この例を最初に見たとき、行に戸惑いました
val sayhello = unfiltered.netty.cycle.Planify {
。掘り下げて書き直したところ、暗黙的に PartialFunction を作成して Planify.apply に渡していることがわかりました。