Question

Anorm de Play2 a un joli DSL de l'analyseur de résultat:

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

Je ne comprends pas cette partie case id ~ name, pourquoi il peut y avoir un ~ entre deux variables?

Je vois case Normalement comme:

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

Mais je ne vois pas case id ~ name.

La source de ~ est là: https://github.com/playframework/play20/blob/master/framework/src/anorm/src/main/scala/sqlparser.scala#l49

Il définit une classe de cas ~:

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

Et j'écris un test simple:

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

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

Il imprime a,b, mais pourquoi la syntaxe est case x ~ y?

Était-ce utile?

La solution

Vous êtes déjà à mi-chemin. C'est possible car Scala vous permet de le faire pour tous les types qui ont été déclarés avec deux Type de paramètres.

Par exemple:

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

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

Bien que cela puisse sembler étrange au début, c'est en fait une très belle propriété car cette syntaxe peut rendre les choses plus lisibles. Considérez l'exemple suivant où un type personnalisé pour un tuple est défini:

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

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

Ici, A |::| B est utilisé comme notation d'infixe pour |::|[A, B]. D'un autre côté, Scala aussi Permet la notation de l'infixation pour la correspondance de motifs (grâce à l'augmentation du rappel), comme dans le cas du constructeur dans l'exemple suivant:

new |::|("Hello","World") match {
  case l |::| r => Console println (l + "," + r)
  case _ =>
}  
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top