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?

Foi útil?

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 _ =>
}  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top