5

I have the following Scala/Play! code:

case class Tweet(from: String, text: String)

implicit val tweetReads = (
 (JsPath \ "from_user_name").read[String] ~
 (JsPath \ "text").read[String]) (Tweet.apply _)

I have several questions regarding the syntax and meaning of the above code:

  • On what class/object is the ~ method invoked on?
  • What is the class/type of the argument to Tweet.apply?

edit 1: full source code:

package models

import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
import play.api.libs.functional.syntax._

case class Tweet(from: String, text: String)

object Tweet {

  implicit val tweetReads = (
      (JsPath \ "from_user_name").read[String] ~
      (JsPath \ "text").read[String])(Tweet.apply _)

  implicit val tweetWrites = (
    (JsPath \ "from").write[String] ~
    (JsPath \ "text").write[String])(unlift(Tweet.unapply))
}
3
  • Please add play version and imports. Commented Jan 8, 2014 at 9:05
  • I use Play! 2.2.1. I have updated my post with the full source code for the model. Commented Jan 8, 2014 at 9:13
  • See docs page for JSON Reads/Writes/Format Combinators v2.8.x Commented Jul 22, 2022 at 20:17

2 Answers 2

8

Step by step:

Method \ on object JsPath

val path1: JsPath = JsPath \ "from_user_name"
val path2: JsPath = JsPath \ "text"

Method read on object of type JsPath

val reads1: Reads[String] = path1.read[String]
val reads2: Reads[String] = path2.read[String]

There is no method ~ in Reads, but there is such method in FunctionalBuilderOps and there is an implicit conversion from M[T] to FunctionalBuilderOps[M[_], T] in play.api.libs.functional.syntax - toFunctionalBuilderOps.

val reads1FunctionalBuilderOps: FunctionalBuilderOps[Reads, String] =
  toFunctionalBuilderOps(reads1)

val canBuild2: CanBuild2[String, String] = reads1FunctionalBuilderOps.~(reads2)

Tweet.apply _ is a scala syntax to create a FunctionN using method with N arguments:

val func: (String, String) => Tweet = Tweet.apply _

There is an apply method in CanBuild2[A, B]. It accepts (A, B) => C and returns Reads[C] (in this case):

implicit val tweetReads: Reads[Tweet] = canBuild2.apply(func)

Actually there are also implicit parameters in JsPath#read, toFunctionalBuilderOps and CanBuild2#apply methods. With that parameters:

val reads1: Reads[String] = path1.read[String](Reads.StringReads)

...
val reads1FunctionalBuilderOps: FunctionalBuilderOps[Reads, String] =
  toFunctionalBuilderOps(reads1)(
    functionalCanBuildApplicative(
      Reads.applicative(JsResult.applicativeJsResult)))

...
implicit val tweetReads: Reads[Tweet] =
  canBuild2.apply(func)(functorReads)
Sign up to request clarification or add additional context in comments.

14 Comments

Hi Senia! Thanks for this detailed reply. I am in the process of studying your reply. I will come up with questions. Bear with me...
Can you please confirm that Tweet.apply _ is an invocation of apply? Also what is the _ placeholder standing for?
@balteo: here Tweet.apply _ is special syntax for something like (a, b) => Tweet.apply(a, b). You need a function of type (A1, A2, ... AN) => R and you have a method (A1, A2, ... AN)R. method _ is a syntax to create new function (object of type FunctionN) using method.
@balteo: it's not one argument. Tweet.apply(_) means one argument, but Tweet.apply _ means all arguments.
@balteo: see The Scala Language Specification 6.7 Method Values.
|
2

I would just add that this is called applicative syntax (for applicative functors). It can be seen for example in scala parser combinator library

If you want to know how to use it with json try to read this. Another example of applicative functors in play framework is form handling. Or you can try to read about scalaz Validation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.