了解Scala块

时间:2013-09-25 14:24:28

标签: scala playframework block

我很难找到具体的答案,我所知道的是微不足道的。我想了解块如何在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源代码的任何引用都有助于我了解它在幕后的工作原理。

2 个答案:

答案 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的第二个版本确实采用了一个完整的匿名函数,它将请求映射到结果。在这种情况下,您可以传递匿名(或命名)函数。