Just want to clarify. If we use higher-order function
(f. that accepts another function as argument). Does it make any sense specify "=>"
sign to call it by-name
. It seems arg-function is calling by-name
anyhow?
There is an example:
// 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) )
And what if I want to call it like this ?:
println( takeFunction2( aFun(2,2)), ... ) // it tries to evaluate immediately when passing
The difference is that if you pass as the first argument a call to a function that returns the (Int, Int) => String
value to use, this call to the generator function is evaluated only once with pass-by-value, compared to being evaluated each time the argument is used in the case of pass-by-name.
Rather contrived example:
var bar = 0
def fnGen() = {
bar += 1
def myFun(v1:Int, v2:Int) = {
(v1 + v2).toString
}
myFun _
}
Now run some calls of your methods above using 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
As you can see, calling takeFunction1
increments bar
only once, while calling takeFunction2
increments bar
twice.
The argument that you're passing by name is aFun
; that's a valid expression, and it does get evaluated both times that takeFunction2
uses it, but since it's just a variable, and you're not doing anything else with it, "evaluating" it is not very meaningful. (It just evaluates to the same value both times.) For pass-by-name to behave differently from pass-by-value, you have to pass in an impure expression (one that has side-effects, or that can evaluate to different values on successive calls, or whatnot).