Scala函数未通过带括号括起来的名称传递(大括号)

Mif*_*eet 3 scala pass-by-name

我希望在执行之前按名称传递一个函数.请考虑以下示例:

class Runner {
  def apply(procedure: => Unit) = {
    println("running procedure")
    procedure
  }
}

new Runner()(println("procedure!")) // #1
new Runner(){println("procedure!")} // #2
Run Code Online (Sandbox Code Playgroud)

调用#1和#2之间的唯一区别在于花括号.而第一次通话输出

running procedure
procedure!
Run Code Online (Sandbox Code Playgroud)

正如所料,仅在第二次通话中

procedure!
Run Code Online (Sandbox Code Playgroud)

打印出来.

似乎在使用花括号时,程序不是通过名称传递,而是执行.为什么在这个例子中,卷曲和圆括号不可互换?

sud*_*d29 10

第一个声明:

new Runner()(println("procedure!")) // #1
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,当使用括号时,apply()方法被调用并println("procedure!")作为参数传递.所以第一个陈述相当于:

new Runner().apply(println("procedure!"))
Run Code Online (Sandbox Code Playgroud)

因此输出是:

running procedure
procedure!
Run Code Online (Sandbox Code Playgroud)

第二个声明:

new Runner(){println("procedure!")} // #2
Run Code Online (Sandbox Code Playgroud)

而在第二种情况下,您通过扩展创建匿名类Runner.因此在第二种情况下,语句println("procedure!")作为构造函数的一部分执行,但apply()不会被调用,因此您只能看到

procedure!
Run Code Online (Sandbox Code Playgroud)

作为输出.

自定义控制结构

我想你打算通过使用第二个语句创建自定义控件结构(虽然对于编译器,它是一个匿名类).如果是这种情况,您可以使用以下语法:

val runner = new Runner()
runner.apply {println("procedure!")}
// OR simply 
runner {println("procedure!")} // this is possible because apply() is defined for Runner
Run Code Online (Sandbox Code Playgroud)