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 件のコメント:
コメントを投稿