1

只是想澄清一下。如果我们使用higher-order function(f. 接受另一个函数作为参数)。"=>"指定符号来调用它是否有意义by-name。似乎 arg-functionby-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
4

2 回答 2

1

不同之处在于,如果您将调用作为第一个参数传递给返回(Int, Int) => String要使用的值的函数,则此对生成器函数的调用仅使用按值传递计算一次,而每次使用参数时都会计算一次在传名的情况下。

相当人为的例子:

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两次。

于 2013-08-30T01:49:42.730 回答
0

您按名称传递的参数是aFun; 这是一个有效的表达式,并且它在takeFunction2使用它的时候都会被评估,但是因为它只是一个变量,而且你没有对它做任何其他事情,“评估”它并不是很有意义。(它只是两次都计算为相同的值。)要使按名称传递的行为与按值传递不同,您必须传入一个不纯的表达式(具有副作用或可以计算为不同的表达式)连续调用或诸如此类的值)。

于 2013-08-30T01:24:37.607 回答