【问题标题】:Understanding Scala Blocks理解 Scala 块
【发布时间】:2013-10-01 04:53:44
【问题描述】:

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

【问题讨论】:

    标签: scala playframework block


    【解决方案1】:

    这里发生了一些事情。 Action 是一个实现 apply() 方法的对象,当您将对象视为函数时,会调用什么。有几个apply()implementations。第一个实现使用按名称参数。

    Scala 支持称为“按名称参数”的概念,它与普通参数一样,只是它们仅在引用它们的代码执行时才被评估。它们有助于创建看起来像是语言一部分的结构,而无需借助宏。在这种情况下,Ok(..) 周围的块只是一个常规的语句块,最后一个的值被用作块的值。您提供的示例在没有大括号的情况下也可以工作。您实际上只是将 Ok 的 apply 方法的结果传递给 Actionapply 方法。

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

    【讨论】:

    • 感谢您的回复。所以从我收集的信息来看,这是 Action.apply() 的语法糖。去掉糖,整个语句会是什么样子?
    • 您拥有的声明本质上是Action.apply(Ok.apply(views.html.index("Your new application is ready.")))。如果您查看我提供的 URL 中apply() 的定义,您会注意到参数类型前面有一个箭头。这只是将其标记为“按名称”参数,如上所述。 (另外,by-name 的语法看起来像不带参数的匿名函数也不是巧合)
    • 顺便说一句,播放文档的链接已损坏。有时,SO 解析器会弄乱包含美元符号的链接。
    【解决方案2】:

    您最好将 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 }
    

    至于具体的Action例子:

    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 的说法 嘿,我是一个接受另一个产生结果的函数的函数

    脱糖调用看起来像

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

    【讨论】:

      猜你喜欢
      • 2012-06-05
      • 1970-01-01
      • 2019-11-14
      • 2012-06-19
      • 2016-08-26
      • 2012-02-19
      • 2015-08-26
      • 2018-09-23
      • 2013-06-22
      相关资源
      最近更新 更多