Wie verstehe ich "case id ~ username=> _" in anorm?
-
29-10-2019 - |
Frage
Play2s Anorm hat einen schönen DSL-Ergebnisparser:
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)
}
}
Ich verstehe diesen Teil nicht case id ~ name
, warum kann es einen ~
zwischen zwei Variablen geben?
Ich sehe case
normalerweise als:
case id => _
case (a,b) => _
case Array(a, _*) => _
Aber ich sehe keinen case id ~ name
.
Die Quelle für ~
ist hier: https://github.com/playframework/Play20/blob/master/framework/src/anorm/src/main/scala/SqlParser.scala#L49
Definiert einen generischen Codetagcode für die Fallklasse:
case class ~[+A, +B](_1:A, _2:B)
Und ich schreibe einen einfachen Test:
case class ~[+A, +B](_1:A, _2:B)
new ~("a","b") match {
case x ~ y => println(x , y)
}
Es wird ~
gedruckt, aber warum lautet die Syntax a,b
?
Lösung
Du bist schon auf halbem Weg.Dies ist möglich, da Sie mit Scala dies für alle Typen tun können, die mit zwei Typparametern deklariert wurden.
Zum Beispiel:
scala> case class Foo[X,Y]()
defined class Foo
scala> val x: Int Foo Double = Foo[Int,Double]()
x: Foo[Int,Double] = Foo()
Obwohl es auf den ersten Blick seltsam erscheint, ist es tatsächlich eine wirklich schöne Eigenschaft, da diese Syntax die Lesbarkeit verbessern kann.Betrachten Sie das folgende Beispiel, in dem ein benutzerdefinierter Typ für ein Tupel definiert ist:
class |::|[A, B](val left: A, val right: B)
object |::| {
def unapply[A, B](o: A |::| B) = Some((o.left, o.right))
}
Hier wird A |::| B
als Infixnotation für |::|[A, B]
verwendet.Auf der anderen Seite erlaubt scala auch die Infixnotation für den Mustervergleich (dank incrop für die Erinnerung), wie im Fall des Konstruktors im folgenden Beispiel:
new |::|("Hello","World") match {
case l |::| r => Console println (l + "," + r)
case _ =>
}