让我们把它简化为:
def index(ref: Option[String]): Action[AnyContent] = Prismic.action(ref)(function)
这样更好,不是吗? index 是从String 的Option 到AnyContent 的Action 的一个函数(一个字),它调用对象Prismic 的action 方法传递两个咖喱参数:ref, index 收到的参数,以及 function(待描述)。
那么让我们分解一下匿名函数:
{ implicit request =>
for {
someDocuments <- ctx.api.forms("everything").ref(ctx.ref).submit()
} yield {
Ok(views.html.index(someDocuments))
}
}
首先,它使用{} 而不是(),因为如果() 是单个参数(有两个参数列表,但每个列表都有一个参数),Scala 允许将其作为参数分隔符删除,并且该参数包含在{}中。
那么,{} 呢?嗯,它是一个包含声明和语句的表达式,新行带有分号推断,其值是最后一条语句的值。也就是这两个表达式的值是一样的,3:
{ 1; 2; 3 }
{
1
2
3
}
当传递一个超过一行的函数时,使用{} 是一种语法约定,即使在本例中,该函数可以只用括号传递。
接下来令人困惑的是implicit request =>,让我们选择更简单的:
x => x * 2
这很容易,对吧?它接受一个参数x,并返回x * 2。在我们的例子中,它是相同的:函数接受一个参数,request,并返回:
for (someDocuments <- somethingSomething())
yield Ok(views.html.index(someDocuments))
也就是说,它调用一些方法,遍历结果,并将这些结果映射到一个新值。这与 Haskell 的 do 表示法非常接近。您可以像下面这样重写它(为了便于阅读,我将其分成多行):
ctx
.api
.forms("everything")
.ref(ctx.ref)
.submit()
.map(someDocuments => Ok(views.html.index(someDocuments)))
所以,回到我们的方法定义,我们有这个:
def index(ref: Option[String]): Action[AnyContent] = Prismic.action(ref)(
implicit request =>
ctx
.api
.forms("everything")
.ref(ctx.ref)
.submit()
.map(someDocuments => Ok(views.html.index(someDocuments)))
)
这里唯一剩下的问题是implicit 是关于什么的。基本上,它使该参数在函数范围内隐式可用。据推测,这些方法调用中至少有一个需要由request 正确分配的隐式参数。如果我知道这些方法中的哪一个需要它,我可以将implicit 明确地放在那里传递request,但由于我不知道,所以我将跳过它。
另一种写法是:
def index(ref: Option[String]): Action[AnyContent] = Prismic.action(ref)({
request =>
implicit val req = request
ctx
.api
.forms("everything")
.ref(ctx.ref)
.submit()
.map(someDocuments => Ok(views.html.index(someDocuments)))
})
我在这里添加了{},因为我在函数体中添加了一个声明,尽管我决定不删除括号,我可以这样做。