Search code examples
scalaplayframeworkplay-json

Scala Play framework FunctionalCanBuild explain


For curiosity sake, for those who study Scala, please explain what the hell that implementation of FunctionalCanBuild is:

So, it is possible to create custom Json Writes for a class in play framework, like this:

implicit val locationWrites: Writes[Location] = (
  (JsPath \ "lat").write[Double] and
  (JsPath \ "long").write[Double]
)(unlift(Location.unapply))

The and is method defined in FunctionalBuilderOps and returns FunctionalBuilder[M]#CanBuild2 which in turn returns FunctionalBuilder[M]#CanBuild3 and so on till FunctionalBuilder[M]#CanBuild22.

So why 22? What if my model has 23 fields? From Scala point of view how to understand this:

fu.fmap[A1 ~ A2, B](canBuild(m1, m2), { case a1 ~ a2 => f(a1, a2) })

Why ~ (and where it is defined) called on generics?

I know, this question may look bit complicated, but stackoverflow is the only hope I have, no googling no scala docs help to understand.


Solution

  • ~ is defined here: https://github.com/playframework/play-json/blob/master/play-functional/src/main/scala/play/api/libs/functional/Products.scala#L9

    A ~ B is like a pair (A, B).

    22 is magic number in Scala:

    Why are scala functions limited to 22 parameters?

    https://underscore.io/blog/posts/2016/10/11/twenty-two.html