我有一个功能:
def nanoTime() = {
println("Getting nano time...")
System.nanoTime // returns nanoTime
}
Run Code Online (Sandbox Code Playgroud)
和另一个功能,它需要一个功能
def printTime(time: => Long) = { // indicates a by-name parameter
println(">> delayed()")
println("Param: " + time)
time // returns time
}
Run Code Online (Sandbox Code Playgroud)
现在就是这样的.当我做:
scala> printTime(nanoTime())
>> delayed()
Getting nano time...
Param: 546632085606127
Getting nano time...
res11: Long = 546632086131624
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我得到了相同的结果:
scala> printTime(nanoTime)
>> delayed()
Getting nano time...
Param: 546622367510997
Getting nano time...
res10: Long = 546622368149903
Run Code Online (Sandbox Code Playgroud)
之间没有区别:
scala> printTime(nanoTime())
Run Code Online (Sandbox Code Playgroud)
和
scala> printTime(nanoTime)
Run Code Online (Sandbox Code Playgroud)
因此,传递函数名称和传递函数名称后跟()没有区别.总是这样,或者这个casE有什么特别之处?
谢谢.
Scala具有参数列表的概念,其中方法可能需要多个参数列表.然而,为方便起见,它还允许省略终端空参数列表.所以
f
f()
f()()
Run Code Online (Sandbox Code Playgroud)
可能都是同一件事 - 直到你看,你才知道f.by-name参数的作用是延迟代码块的执行.现在,正式如果我们有
def f0: String = "salmon"
def f1(): String = "herring"
def f2()(): String = "halibut"
Run Code Online (Sandbox Code Playgroud)
f0如果转换为函数,那么你希望匹配一个名字参数而不是其他参数.具体来说,你会期望
f0 <==> => String
f1 <==> () => String
f2 <==> () => () => String
Run Code Online (Sandbox Code Playgroud)
转换时.让我们看看在请求时实际发生了什么f _:
scala> f0 _
res4: () => String = <function0>
scala> f1 _
res5: () => String = <function0>
scala> f2 _
res6: () => () => String = <function0>
Run Code Online (Sandbox Code Playgroud)
那好吧; 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.
Run Code Online (Sandbox Code Playgroud)
你没有看到区别的原因是,为了返回a Long,by-name参数已经填充了缺失(),但随后将整个事物包装在代码块中以便稍后执行.
(另请注意,名字参数实际上只是Function0在幕后 - 也就是说,x: => A实际上x: () => A- 并且"零参数块"的东西只是一个编译器小说.实际上,所有参数块都是编译器小说--JVM只知道一个单一的参数列表.正是这种无块的小说,再加上那些关心空洞的小说,导致观察到的行为.)
如果从空参数块请求函数,那么事情就像这样:
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
Run Code Online (Sandbox Code Playgroud)
现在parens 很重要因为编译器试图将方法签名与函数签名匹配.副名称参数情况的特殊情况不再适用.
| 归档时间: |
|
| 查看次数: |
329 次 |
| 最近记录: |