【问题标题】:Syntax and meaning of a Scala/Play! code sampleScala/Play 的语法和含义!代码示例
【发布时间】:2014-01-08 08:51:08
【问题描述】:

我有以下 Scala/Play! 代码:

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

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

我有关于上述代码的语法和含义的几个问题

  • 在哪个类/对象上调用了~ 方法?
  • Tweet.apply 的参数的类/类型是什么?

编辑 1:完整源代码:

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

【问题讨论】:

  • 请添加play版本和导入。
  • 我使用 Play! 2.2.1。我已经用模型的完整源代码更新了我的帖子。

标签: scala playframework


【解决方案1】:

一步一步:

对象 JsPath 上的方法 \

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

JsPath 类型对象上的方法 read

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

Reads 中没有方法~,但在FunctionalBuilderOps 中有这样的方法,并且在play.api.libs.functional.syntax - toFunctionalBuilderOps 中有从M[T]FunctionalBuilderOps[M[_], T] 的隐式转换。

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

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

Tweet.apply _ 是一种使用带有N 参数的方法创建FunctionN 的scala 语法:

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

CanBuild2[A, B] 中有一个apply 方法。它接受(A, B) => C 并返回Reads[C](在这种情况下):

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

其实JsPath#readtoFunctionalBuilderOpsCanBuild2#apply方法中也有隐式参数。使用该参数:

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)

【讨论】:

  • 嗨塞尼亚!感谢您的详细回复。我正在研究你的回复。我会提出问题。忍受我...
  • 您能否确认Tweet.apply _ 是对apply 的调用?还有_ 占位符代表什么?
  • @balteo:这里的Tweet.apply _(a, b) => Tweet.apply(a, b) 之类的特殊语法。你需要一个(A1, A2, ... AN) => R 类型的函数并且你有一个(A1, A2, ... AN)R 方法。 method _ 是一种使用方法创建新函数(FunctionN 类型的对象)的语法。
  • @balteo:不是one argumentTweet.apply(_) 表示one argument,但Tweet.apply _ 表示all arguments
  • @balteo:参见The Scala Language Specification 6.7 方法值
【解决方案2】:

我只想补充一点,这称为应用语法(适用于应用函子)。例如在scala parser combinator library中可以看到

如果您想知道如何将它与 json 一起使用,请尝试阅读 this。游戏框架中应用函子的另一个例子是form handling。或者您可以尝试阅读有关 scalaz 验证的信息。

【讨论】:

    猜你喜欢
    • 2013-09-25
    • 2011-02-26
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    相关资源
    最近更新 更多