Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
399 views
in Technique[技术] by (71.8m points)

playframework - Syntax and meaning of a Scala/Play! code sample

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))
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...