只想澄清一下。如果我们使用higher-order function
(f。接受另一个函数作为参数)。是否有必要指定"=>"
符号来调用它by-name
。似乎arg-function无论如何都在调用by-name
?
有一个例子:
// 1.
// the function that accepts arg-function with: two int params and returning String
// the function passing v1 & v2 as parameters to arg-function, invoking arg-function 2 times, connecting the result to one string
def takeFunction1(f: (Int, Int) => String, v1:Int, v2:Int ): String = {
f(v1, v2) + f(v1, v2)
}
// 2. same as #1 but calling arg-function by-name
def takeFunction2(f: => ((Int, Int) => String), v1:Int, v2:Int ): String = {
f(v1, v2) + f(v1, v2)
}
def aFun(v1:Int, v2:Int) : String = {
(v1 + v2).toString
}
// --
println( takeFunction1( aFun, 2, 2) )
println( takeFunction2( aFun, 2, 2) )
如果我想这样称呼它怎么办?:
println( takeFunction2( aFun(2,2)), ... ) // it tries to evaluate immediately when passing
答案 0 :(得分:1)
不同之处在于,如果作为第一个参数传递一个函数,该函数返回要使用的(Int, Int) => String
值,那么对生成器函数的调用仅使用pass-by-value计算一次,与每次在名称传递的情况下使用参数时进行评估。
相当人为的例子:
var bar = 0
def fnGen() = {
bar += 1
def myFun(v1:Int, v2:Int) = {
(v1 + v2).toString
}
myFun _
}
现在使用fnGen:
对上面的方法进行一些调用scala> println( takeFunction1( fnGen(), 2, 2) )
44
scala> bar
res1: Int = 1
scala> println( takeFunction2( fnGen(), 2, 2) )
44
scala> bar
res3: Int = 3
如您所见,调用takeFunction1
仅增加bar
一次,同时调用takeFunction2
增加bar
两次。
答案 1 :(得分:0)
您通过名称传递的论点是aFun
;这是一个有效的表达式,并且它会在takeFunction2
使用它的时候进行评估,但由于它只是一个变量,并且你没有对它做任何其他事情,“评估”它并不是很有意义。 (它只是两次计算相同的值。)对于按名称传递的行为与传值不同,你必须传入一个不纯的表达式(一个有副作用,或者可以评估为不同的表达式)连续调用的值,或诸如此类的。)