pがパターンの時、val p = eは以下の様に展開される。
val $x = e match {case p => (x1, . . . , xn)} val x1 = $x._1 . . . val xn = $x._n※The Scala Language Specification(PDF)のp.36参照(タプルが{}になっているのは古い仕様?なので↑では()に直しています)。
簡単な例だと、タプルを使って同時にvalに代入できる。
val (x, y) = (1, 2) // ↑は↓に展開され val tmp = (1, 2) match {case (a, b) => (a, b)} val x = tmp._1 val y = tmp._2 // 結局↓と同じ val x = 1 val y = 2
Liftで↓なコードがあって、意味が分からなかったのだが、やっと理解できた。
// net/liftweb/http/Req.scala l.275 case class ParamCalcInfo(paramNames: List[String], params: Map[String, List[String]], uploadedFiles: List[FileParamHolder], body: Box[Array[Byte]]) // l.284 class Req(val path: ParsePath, val contextPath: String, val requestType: RequestType, val contentType: Box[String], val request: HTTPRequest, val nanoStart: Long, val nanoEnd: Long, private[http] val paramCalculator: () => ParamCalcInfo, // *2 private[http] val addlParams: Map[String, String]) extends HasParams { // (省略) // l.342 lazy val ParamCalcInfo(paramNames: List[String], // *1 _params: Map[String, List[String]], uploadedFiles: List[FileParamHolder], body: Box[Array[Byte]]) = paramCalculator() // (省略) }
- なぜ突然valの後にcase classが…? と思ったらこれがパターンマッチ。コンストラクタで指定した関数paramCalculator(*2)がParamCalcInfoを返すので、ParamCalcInfoの各valがそれぞれparamNames, _params, uploadedFiles, bodyに束縛され、Req.body等として使える。つまり、↓の様に展開されているということと理解。
val tmp = paramCalculator() match { case ParamCalcInfo(a, b, c, d) => (a, b, c, d) } val paramNames = tmp._1 val _params = tmp._2 val uploadedFiles = tmp._3 val body = tmp._4
0 件のコメント:
コメントを投稿