Como entender “case id ~ username=> _” no anorm?
-
29-10-2019 - |
Pergunta
O anorm do Play2 tem um bom DSL de analisador 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)
}
}
Não entendo esta parte case id ~ name
, por que pode haver um ~
entre duas variáveis?
Vejo case
normalmente como:
case id => _
case (a,b) => _
case Array(a, _*) => _
Mas não vejo case id ~ name
.
A fonte do ~
está aqui: https://github.com/playframework/Play20/blob/master/framework/src/anorm/src/main/scala/SqlParser.scala#L49
Ele define uma classe de caso ~
:
case class ~[+A, +B](_1:A, _2:B)
E eu escrevo um teste simples:
case class ~[+A, +B](_1:A, _2:B)
new ~("a","b") match {
case x ~ y => println(x , y)
}
Ele imprime a,b
, mas por que a sintaxe é case x ~ y
?
Solução
Você já está na metade do caminho.É possível porque Scala permite que você faça isso para todos os tipos que foram declarados com dois parâmetros de tipo.
Por exemplo:
scala> case class Foo[X,Y]()
defined class Foo
scala> val x: Int Foo Double = Foo[Int,Double]()
x: Foo[Int,Double] = Foo()
Embora possa parecer estranho no início, na verdade é uma propriedade muito boa, pois essa sintaxe pode tornar as coisas mais legíveis.Considere o seguinte exemplo, onde um tipo personalizado para uma tupla é definido:
class |::|[A, B](val left: A, val right: B)
object |::| {
def unapply[A, B](o: A |::| B) = Some((o.left, o.right))
}
Aqui, A |::| B
é usado como notação de infixo para |::|[A, B]
.Por outro lado, scala também permite notação de infixo para correspondência de padrões (graças ao incrop pelo lembrete), como no caso do construtor no exemplo a seguir:
new |::|("Hello","World") match {
case l |::| r => Console println (l + "," + r)
case _ =>
}