我有一个功能:
def nanoTime() = {
println("Getting nano time...")
System.nanoTime // returns nanoTime
}
和另一个函数,它带有一个函数
def printTime(time: => Long) = { // indicates a by-name parameter
println(">> delayed()")
println("Param: " + time)
time // returns time
}
现在就是这样。当我这样做时:
scala> printTime(nanoTime())
>> delayed()
Getting nano time...
Param: 546632085606127
Getting nano time...
res11: Long = 546632086131624
我得到的结果与我一样:
scala> printTime(nanoTime)
>> delayed()
Getting nano time...
Param: 546622367510997
Getting nano time...
res10: Long = 546622368149903
之间没有区别:
scala> printTime(nanoTime())
和
scala> printTime(nanoTime)
因此,传递函数名称并传递函数名称后跟()没有区别。总是这样,或者这个casE有什么特别之处?
感谢。
答案 0 :(得分:8)
Scala具有参数列表的概念,其中方法可能需要多个参数列表。然而,为方便起见,它还允许省略终端空参数列表。所以
f
f()
f()()
可能都是一回事 - 在你看f
之前你不知道。 by-name参数的作用是延迟代码块的执行。现在,正式如果我们有
def f0: String = "salmon"
def f1(): String = "herring"
def f2()(): String = "halibut"
然后,如果转换为函数,您可能希望f0
匹配一个名字参数而其他参数不匹配。具体来说,你会期待
f0 <==> => String
f1 <==> () => String
f2 <==> () => () => String
转换时让我们看看通过f _
请求时实际发生的事情:
scala> f0 _
res4: () => String = <function0>
scala> f1 _
res5: () => String = <function0>
scala> f2 _
res6: () => () => String = <function0>
好吧,好吧f0
实际上转换为一个带有一个空参数块而不是零的函数(这是一个by-name参数的样子)。所以事实证明你的by-name参数根本没有将你的方法转换成函数 - 类型签名将不匹配!
相反,它的原因是这样的:
// I need a code block that returns a long
nanoTime // Wait, there is no nanoTime exactly
nanoTime() // Aha, that works! Must have meant that
: => { nanoTime() } // There, nicely packaged.
您认为没有区别的原因是,为了返回Long
,by-name参数已经填充了缺少的()
,但随后将整个事物包装在代码块中稍后执行。
(另请注意,名称参数实际只是Function0
在幕后 - 即x: => A
真的是x: () => A
- 并且“零参数块”事物只是一个编译器小说。实际上,所有参数块都是编译器小说--JVM只知道一个参数列表。而且这是一个无块的小说,加上谁关心 - 关于-empty-parens小说,导致观察到的行为。)
如果从空参数块请求函数,那么事情就像这样:
def printF(f: () => String) = println(f())
scala> printF(f0)
<console>:23: error: type mismatch;
found : String
required: () => String
printF(f0)
^
scala> printF(f1)
herring
scala> printF(f2)
<console>:23: error: type mismatch;
found : () => String
required: String
printF(f2)
scala> printF(f2())
halibut
现在parens 做很重要,因为编译器正在尝试将方法签名与函数签名匹配。副名参数情况的特殊情况不再适用。