Pregunta

El anorm de Play2 tiene un buen DSL de analizador de resultados:

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

No entiendo esta parte case id ~ name, ¿por qué puede haber un ~ entre dos variables?

Veo case normalmente como:

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

Pero no veo case id ~ name.

La fuente de ~ está aquí: https://github.com/playframework/Play20/blob/master/framework/src/anorm/src/main/scala/SqlParser.scala#L49

Define una clase de caso ~:

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

Y escribo una prueba sencilla:

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

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

Imprime a,b, pero ¿por qué la sintaxis es case x ~ y?

¿Fue útil?

Solución

Ya estás a mitad de camino.Es posible porque Scala le permite hacer eso para todos los tipos que han sido declarados con dos parámetros de tipo.

Por ejemplo:

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

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

Si bien puede parecer extraño al principio, en realidad es una propiedad realmente agradable ya que esta sintaxis puede hacer que las cosas sean más legibles.Considere el siguiente ejemplo donde se define un tipo personalizado para una tupla:

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

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

Aquí, A |::| B se usa como notación infija para |::|[A, B].Por otro lado, scala también permite la notación infija para la coincidencia de patrones (gracias a incrop para el recordatorio), como en el caso del constructor en el siguiente ejemplo:

new |::|("Hello","World") match {
  case l |::| r => Console println (l + "," + r)
  case _ =>
}  
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top