Domanda

L'anorm di Play2 ha un bel DSL del parser dei risultati:

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) 
  }
}

Non capisco questa parte case id ~ name, perché può esserci un ~ tra due variabili?

Vedo case normalmente come:

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

Ma non vedo case id ~ name.

La fonte di ~ è qui: https://github.com/playframework/Play20/blob/master/framework/src/anorm/src/main/scala/SqlParser.scala#L49

Definisce una classe case ~:

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

E scrivo un semplice test:

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

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

Stampa a,b, ma perché la sintassi è case x ~ y?

È stato utile?

Soluzione

You're already halfway there. It is possible because Scala lets you do that for all types that have been declared with two type parameters.

For example:

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

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

While it may seem odd at first, it's actually a really nice property as this syntax can make things more readable. Consider the following example where a custom type for a tuple is defined:

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

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

Here, A |::| B is used as infix notation for |::|[A, B]. On the other hand, scala also allows infix notation for pattern matching (thanks to incrop for the reminder), as in case of the constructor in the following example:

new |::|("Hello","World") match {
  case l |::| r => Console println (l + "," + r)
  case _ =>
}  
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top