首先,我有这个功能:
def number5()={
println("number 5 starting")
println("number 5 exiting")
5
}
然后:
def giveMeCallByNameParameter(f: =>Int)={
println("starting")
f
println("exiting")
}
我打电话的时候:
giveMeCallByNameParameter(number5)
我得到了这个结果:
starting
number 5 starting
number 5 exiting
exiting
如果我也有这个功能:
def giveMeAnotherFunction(f: ()=>Int)={
println("starting")
f()
println("exiting")
}
我称之为:
giveMeAnotherFunction(number5)
我得到了相同的结果:
starting
number 5 starting
number 5 exiting
exiting
那么,它们有什么不同吗?除了是否有括号之外?
如果他们没有什么不同?那么我们为什么要按名称命名这个术语呢?
答案 0 :(得分:3)
名称参数可以是任何有效的表达式。函数也是有效的表达式,但只是一种表达式。
按名称参数和按值参数之间的最大区别在于,在传递给函数之前,评估了按值参数(最常见的函数参数)。至少在传递给函数之后,名称参数的评估被延迟。函数本身可能会或可能不会评估参数,它没有义务。
事实上,函数具有相同类型的属性,但正如我之前所说,函数只是一种表达式,而按名称参数可以采用任何类型的有效表达式。
副名称参数的一个很好的用例是构建自定义断言函数:
def byNameAssert(predicate: => Boolean) =
if (assertionsEnabled && !predicate)
throw new AssertionError
这样,您可以通过控制assertionsEnabled
值来关闭对断言条件的评估。
如果未启用断言,您甚至可以使用一个通常会抛出的表达式,而不会产生异常:
byNameAssert(x / 0 == 0)
还要注意表达式x / 0 == 0
不是函数!按名称参数可以采用任何类型的表达式,但至少会在调用函数之后推迟评估。
希望这有帮助!
答案 1 :(得分:2)
在这个特定的例子中,两者看起来都一样。但请考虑这个用例
giveMeCallByNameParameter(number5 * number5)
你得到这个结果:
开始
5号出发 5号退出
5号出发 5号退出
退出
如果您尝试在giveMeAnotherFunction
上执行相同操作,则无法编译
阶> giveMeAnotherFunction(number5()* number5())
:10:错误:类型不匹配;
发现:Int
必需:()=>诠释
giveMeAnotherFunction(number5()* number5())
您必须发送一个不仅仅是任何表达式的函数
giveMeAnotherFunction(() => number5 * number5)
答案 2 :(得分:1)
据我所知,至少在你的例子中没有区别。
答案 3 :(得分:0)
有区别。
因此,您将方法number5
更改为某个功能,您不能使用按名称调用,但您可以在函数中使用
def number5()={
println("number 5 starting")
println("number 5 exiting")
5
}
def func: () => Int = number5 // change method to function
def giveMeCallByNameParameter(f: =>Int)={
println("starting")
f
println("exiting")
}
giveMeCallByNameParameter(func) //compilation error
def giveMeAnotherFunction(f: ()=>Int)={
println("starting")
f()
println("exiting")
}
giveMeAnotherFunction(func) // this is fine
此外,您可以在 giveMeAnotherFunction 中使用方法的原因是功能,原因是 ETA-expansion 。有很多使用它的例子,如map,foldLeft等。