如何理解anorm中的"case id~username => _"?

Fre*_*ind 3 scala anorm playframework-2.0

Play2的anorm有一个很好的DSL结果解析器:

case class User(id:Pk[String], name:String)

object User {
  val parser = get[String]("id") ~ get[String]("name") map { 
    case id ~ name => User(id,name) 
  }
}
Run Code Online (Sandbox Code Playgroud)

我不明白这部分case id ~ name,为什么~两个变量之间可以存在?

case通常认为:

case id => _
case (a,b) => _
case Array(a, _*) => _
Run Code Online (Sandbox Code Playgroud)

但我没有看到case id ~ name.

来源~是:https://github.com/playframework/Play20/blob/master/framework/src/anorm/src/main/scala/SqlParser.scala#L49

它定义了一个案例类~:

case class ~[+A, +B](_1:A, _2:B)
Run Code Online (Sandbox Code Playgroud)

我写了一个简单的测试:

case class ~[+A, +B](_1:A, _2:B)

new ~("a","b") match {
    case x ~ y => println(x , y)
}    
Run Code Online (Sandbox Code Playgroud)

它打印a,b,但为什么语法是case x ~ y

fot*_*ton 7

你已经到了一半了.这是可能的,因为Scala允许您对已使用两个类型参数声明的所有类型执行此操作.

例如:

scala> case class Foo[X,Y]()
defined class Foo

scala> val x: Int Foo Double = Foo[Int,Double]()
x: Foo[Int,Double] = Foo()
Run Code Online (Sandbox Code Playgroud)

虽然起初看起来很奇怪,但它实际上是一个非常好的属性,因为这种语法可以使事情更具可读性.请考虑以下示例,其中定义了元组的自定义类型:

class |::|[A, B](val left: A, val right: B)

object |::| {
  def unapply[A, B](o: A |::| B) = Some((o.left, o.right))
}
Run Code Online (Sandbox Code Playgroud)

这里,A |::| B用作中缀表示法|::|[A, B].另一方面,scala 允许使用中缀表示法进行模式匹配(感谢incrop for the reminder),如下例中的构造函数:

new |::|("Hello","World") match {
  case l |::| r => Console println (l + "," + r)
  case _ =>
}  
Run Code Online (Sandbox Code Playgroud)