Как понять "case id ~ username => _" в anorm? - PullRequest
3 голосов
/ 22 февраля 2012

У Play2 есть хороший 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) 
  }
}

Я не понимаю эту часть case id ~ name, почему между двумя переменными может быть ~?

Я вижу case обычно как:

case id => _
case (a,b) => _
case Array(a, _*) => _

Но я не вижу 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)

И я пишу простой тест:

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

new ~("a","b") match {
    case x ~ y => println(x , y)
}    

Он печатает a,b, но почему синтаксис case x ~ y

1 Ответ

7 голосов
/ 22 февраля 2012

Ты уже на полпути. Это возможно, потому что Scala позволяет вам делать это для всех типов, которые были объявлены с двумя параметрами типа.

Например:

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

scala> val x: Int Foo Double = Foo[Int,Double]()
x: Foo[Int,Double] = Foo()

Поначалу это может показаться странным, но на самом деле это действительно хорошее свойство, так как этот синтаксис может сделать вещи более читабельными. Рассмотрим следующий пример, в котором определен пользовательский тип для кортежа:

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

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

Здесь A |::| B используется как инфиксная запись для |::|[A, B]. С другой стороны, scala также позволяет использовать инфиксную нотацию для сопоставления с образцом (спасибо incrop за напоминание), как в случае конструктора в следующем примере:

new |::|("Hello","World") match {
  case l |::| r => Console println (l + "," + r)
  case _ =>
}  
...