我很难找到具体的答案,我所知道的是微不足道的。我想了解块如何在Scala中工作。我来自java / ruby背景,似乎scala有一种完全不同的使用块的方式。
以下代码来自Play! Framework website。我想了解 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源代码的任何引用都有助于我了解它在幕后的工作原理。
答案 0 :(得分:22)
你最好将scala块视为java匿名类(例如像Guava Functions)而不是ruby块。实际上,如果你反编译scala代码,你会看到或多或少相同的代码(taken from Guava examples):
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)
。接下来,you can drop round braces when your call isn't ambiguous,是的,它实际上是一个被调用的方法,如:
def index = Action({
Ok(views.html.index("Your new application is ready."))
})
并且有这样的签名:
object Action {
def apply(block: => Result) = ???
}
正如@yan已经说过的那样,scala方式可以说嘿,我是一个接受另一个产生结果的函数的函数
Desugared调用看起来像
def index = Action.apply(new AbstractFunction[Result] {
def apply() = Ok.apply(views.html.index.apply("..."))
})
答案 1 :(得分:8)
这里有一些事情发生。 Action
是一个实现apply()
方法的对象,当您将对象视为函数时,会调用什么。有几个apply()
implementations。第一个实现使用by-name参数。
Scala支持一种称为“按名称参数”的概念,它与普通参数类似,只是在执行引用它们的代码时才会对它们进行评估。它们有助于创建看起来像是语言一部分而不需要使用宏的构造。在这种情况下,Ok(..)
周围的块只是一个常规语句块,最后一个值用作块的值。您提供的示例也可以在没有大括号的情况下工作。您基本上只是将Ok的apply
方法的结果传递给Action
的{{1}}方法。
apply
的第二个版本确实采用了一个完整的匿名函数,它将请求映射到结果。在这种情况下,您可以传递匿名(或命名)函数。