Scala:将函数作为花括号之间的代码块传递

Pio*_*zyk 34 syntax scala

有几次我看到像这样的Scala代码:

object Doer{
   def doStuff(op: => Unit) {
      op
   }
}
Run Code Online (Sandbox Code Playgroud)

以这种方式调用:

Doer.doStuff{
      println("Done")
}
Run Code Online (Sandbox Code Playgroud)

对我来说奇怪的是函数如何作为花括号之间的代码块传递给另一个函数.甚至没有括号通常标记参数列表的开头和结尾.

这个Scala语法/功能的名称是什么?在什么情况下我可以使用它?它在哪里记录?

Dan*_*mon 46

这被称为nullary函数thunk,并且是一个名为call-by-name的例子:http://www.scala-lang.org/old/node/138

你可以在任何有参数列表的地方使用nullaries.它们基本上只是零参数函数的语法糖,使它们看起来像普通值,并且只要它们被引用就会被调用.

所以

def doSomething(op: => Unit) {
  op
}
doSomething {
  println("Hello!")
}
Run Code Online (Sandbox Code Playgroud)

与以下内容完全相同:

def doSomething(op: () => Unit) {
  op()
}
doSomething(() => println("Hello!"))
Run Code Online (Sandbox Code Playgroud)

要记住null的一件事是每次引用时都会调用它们,所以类似于:

def foo(op: => Int) = op + op
foo {
  println("foo")
  5
}
Run Code Online (Sandbox Code Playgroud)

将两次打印"foo".

编辑:为了扩展Randall的注释,nullary函数与zero-arg函数不同的一个重要方法是nullary不是一等值.例如,你可以有一个,List[() => Int]但你不能拥有List[=> Int].如果你有类似的东西:

def foo(i: => Int) = List(i)
Run Code Online (Sandbox Code Playgroud)

您没有将nullary函数添加到列表中,只是它的返回值.

  • 最好不要将thunk视为函数.你完全无法使用thunk,就好像它是一个函数,因为你不能选择将它视为要存储或传递的"Function"值.您只能触发实际参数表达式的评估(任意数量). (4认同)