我曾几次看到这样的Scala代码:
object Doer{
def doStuff(op: => Unit) {
op
}
}
以这种方式调用:
Doer.doStuff{
println("Done")
}
对我来说奇怪的是,一个函数被传递到另一个函数,只作为花括号之间的一块代码。甚至没有括号来标记参数列表的开始和结束。
这种Scala语法/特性的名称是什么?我可以在什么情况下使用它?它在哪里有文档记录?
这被称为 nullary function 或者 thunk,是一种按名称调用评估的示例:http://www.scala-lang.org/old/node/138
您可以在任何需要参数列表的地方使用 nullaries。它们基本上只是围绕零参数函数的语法糖,使它们看起来像普通值,并在引用它们时调用。
所以
def doSomething(op: => Unit) {
op
}
doSomething {
println("Hello!")
}
与以下内容完全相同:
def doSomething(op: () => Unit) {
op()
}
doSomething(() => println("Hello!"))
在处理空参数函数时需要牢记一点,即每次引用该函数时都会调用它,因此以下代码:
def foo(op: => Int) = op + op
foo {
println("foo")
5
}
将会打印两次 "foo"。
编辑:根据Randall的评论,空元函数与零参数函数之间的一个重要区别是,空元函数不是一等值。例如,您可以有一个List[() => Int]
但您不能有一个List[=> Int]
。如果您有像下面这样的内容:
def foo(i: => Int) = List(i)
你没有将零元函数添加到列表中,只添加了它的返回值。
def f(op: =>Int) = op _
,还有 def g(op: =>Int) = f(op)
,所以 g(8)
不会被评估。换句话说,按名称调用的参数是一个无参方法类型,就像 def x
。 - som-snytt=>A
的精确方式,它被评估每次引用时都是一个表达式,就像按名称传递的参数一样。(对我来说,这帮助我不去考虑它是如何实现或编码的。) - som-snytt
f(args)
或者f {block}
,但是除了中缀表达式x op y
之外,不能省略标点符号。该块是一个匿名函数,只能写成{ case x => }
。 - som-snytt