斯卡拉。按名称调用的高阶函数。是否有意义

时间:2013-08-30 01:17:00

标签: scala

只想澄清一下。如果我们使用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

2 个答案:

答案 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使用它的时候进行评估,但由于它只是一个变量,并且你没有对它做任何其他事情,“评估”它并不是很有意义。 (它只是两次计算相同的值。)对于按名称传递的行为与传值不同,你必须传入一个不纯的表达式(一个有副作用,或者可以评估为不同的表达式)连续调用的值,或诸如此类的。)