理解Scala代码块

24

我很难找到特定的答案,尽管它是一些微不足道的事情。 我想了解Scala中块的工作原理。 我来自于Java / Ruby背景,似乎Scala使用块的方式完全不同。

以下代码来自Play! Framework网站。我想了解Action在语义上是什么。 它是一个接受块的对象或函数,还是两者都不是?

object Application extends Controller {

  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }

}

如果它是一个函数,也许它只是以下语法糖(在这种情况下,Scala 是如何在后台传递块的呢):

  def index = Action({
    Ok(views.html.index("Your new application is ready."))
  })

还是我不知道的某种 Scala 语法?

有关 Scala 源代码的任何参考资料都将帮助我了解这背后的工作原理。

2个回答

25

您最好将Scala块视为Java匿名类(例如,像Guava函数),而不是像Ruby块。实际上,如果您反编译Scala代码,您会看到更多或更少相同的代码(取自Guava示例):

Function<String, Integer> lengthFunction = new Function<String, Integer>() {
  public Integer apply(String string) {
    return string.length();
  }
};

区别在于,Scala 提供了大量的语法糖,使你可以将上述代码编写为:
val lengthFunction = { string: String => string.length }

关于具体的操作示例:
def index = Action({
    Ok(views.html.index("Your new application is ready."))
  })

这里的Action很可能是带有apply方法的对象。另一个Scala语法糖:语言允许您编写Foo(bar)并且意思是Foo.apply(bar)。接下来,当您的调用不含歧义时,您可以省略圆括号, 所以是的,实际上是调用了一个方法:
def index = Action({
    Ok(views.html.index("Your new application is ready."))
})

并且有这样的签名:

object Action {
  def apply(block: => Result) = ???
}

正如@yan所说,这是scala的方式来表示“嘿,我是一个接受另一个产生结果的函数”的。

展开后的调用将会是这样的

def index = Action.apply(new AbstractFunction[Result] {
        def apply() = Ok.apply(views.html.index.apply("..."))
})

8
这里有几个要点。 Action 是一个实现了 apply() 方法的对象,在将这个对象作为函数使用时会调用该方法。存在一些 apply()实现。第一个实现使用了按名称参数。
Scala 支持一种被称为“按名称参数”的概念,它们与普通参数类似,但只有在引用它们的代码被执行时才会进行评估。它们有助于创建看起来像是语言一部分的构造,而不需要使用宏。在这种情况下,包围 Ok(..) 的块只是一组常规语句,其中最后一个语句的值被用作块的值。你提供的示例也可以不使用花括号正常工作。实质上,你只需将 Ok 的 apply 方法的结果传递给 Action 的 apply 方法即可。 apply() 的第二个版本确实接受一个完整的匿名函数,将一个 Request 映射到一个 Result。在这种情况下,你可以传递一个匿名(或命名)函数。

谢谢回复。从我的理解来看,这是Action.apply()的语法糖。如果去掉语法糖,整个语句会是什么样子? - b1nd
你所看到的语句本质上是 Action.apply(Ok.apply(views.html.index("Your new application is ready.")))。如果你查看我提供的URL中的 apply() 定义,你会注意到参数类型前面有一个箭头。这只是标记它为“按名称”参数,如上所述。(此外,按名称的语法之所以看起来像没有参数的匿名函数,这不是巧合) - yan
顺便说一下,Play文档的链接已经失效了。有时候,SO解析器会弄乱包含美元符号的链接。 - om-nom-nom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接