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?

War es hilfreich?

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 _ =>
}  

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top