理解 Scala 块

Posted

技术标签:

【中文标题】理解 Scala 块【英文标题】:Understanding Scala Blocks 【发布时间】: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 源代码的引用都将帮助我了解它是如何在幕后工作的。

【问题讨论】:

【参考方案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("..."))
)

【讨论】:

以上是关于理解 Scala 块的主要内容,如果未能解决你的问题,请参考以下文章

Scala Swing 中的听众和反应

关于scala的简单理解,对象,属性

scala中的理解半并行调用

理解Scala的函数式编程思想

尝试理解 Kafka Scala 语法

理解 Scala 中的“类型”关键字的作用