【问题标题】:Function parameters evaluation in Scala (functional programming)Scala 中的函数参数评估(函数式编程)
【发布时间】:2015-01-01 11:04:34
【问题描述】:

请在下面找到有关 Scala 函数式编程的 Coursera 在线课程(第 2.3 课)的一段代码。

package week2
import math.abs

object lecture2_3_next {
  def fixedPoint(f: Double => Double)(firstGuess: Double): Double = {
    val tolerance = 0.0001
    def isCloseEnough(x: Double, y: Double): Boolean = abs((x - y) / x) / x < tolerance
    def iterate(guess: Double): Double = {
      val next = f(guess)
      if (isCloseEnough(guess, next)) next
      else iterate(next)
    }
    iterate(firstGuess)
  }                                              

  def averageDamp(f: Double => Double)(x: Double): Double = (x + f(x)) / 2

  def sqrt(x: Double): Double = fixedPoint(averageDamp(y => x / y))(1)

  sqrt(2)                                         

} 

在我试图理解这段代码时,有几点阻碍了我。

我希望您能帮助我理解这段代码。

让我烦恼的两点是: - 当您调用 averageDamp 时,传递的函数中有 2 个参数“x”和“y”(例如averageDamp(y =&gt; x / y))但您从未在 averageDamp 函数的定义中指定“y”参数(例如def averageDamp(f: Double =&gt; Double)(x: Double): Double = (x + f(x)) / 2 )。 scala 编译器在哪里以及如何评估“y”参数。 - 第二点可能和第一点有关,其实我也不知道。当我调用averageDamp 函数时,我只传递函数'f' 参数(例如y =&gt; x / y),但我不传递函数的第二个参数'x'(例如(x: Double) 第二个参数)。在这种情况下,scala 编译器如何评估“x”参数以呈现 averageDamp 调用的结果。

我想我错过了有关 scala 和函数式编程的评估或替换模型的一些内容。

感谢您的帮助,新年快乐!

埃尔韦

【问题讨论】:

    标签: scala functional-programming evaluation


    【解决方案1】:

    1) 您没有将xy 参数作为f 传递,而是传递了一个函数。该函数定义为y =&gt; x / y,其中y 只是此函数参数的占位符,而x 在此上下文中是一个固定值,因为它作为sqrt 方法的参数给出(在示例x 是 2)。除了花哨的 lambda 语法,您也可以编写

    def sqrt(x: Double): Double = fixedPoint(averageDamp(
        new Function1[Double,Double] {
           def apply(y:Double):Double = x / y
        }
    ))(1)
    

    这没什么神奇的,只是一个缩写。

    2) 当你有第二个参数列表,并且在调用方法时不使用它,你会做一些叫做“currying”的事情,你会得到一个偏函数。考虑

    def add(x:Int)(y:Int) = x + y
    

    如果你调用它为add(2)(3),一切都是“正常的”,你会得到5。但如果你调用add(2),第二个参数仍然是“丢失”,你会得到一个期望这个丢失的函数第二个参数,所以你有类似y =&gt; 2 + y

    【讨论】:

    • 好的,谢谢,我想这让我思路清晰。如果我在 Gregor Rayman 的帮助下重新制定你的答案。我会说我的函数averageDamp 被传递给调用函数fixedPoint 并被val next= f(guess) 行使用。 guess 是我在 y =&gt; x/y 中寻找的 'y' 参数,而 x 是传递给 sqrt 函数的参数。
    【解决方案2】:

    x 不是(匿名)函数的参数,它是函数sqrt 的参数。对于匿名函数,它是一个绑定闭包。

    为了更明显,让我们重写它并使用命名函数而不是匿名函数:

    def sqrt(x: Double): Double = fixedPoint(averageDamp(y => x / y))(1)
    

    可以改写成这样:

    def sqrt(x: Double): Double = {
       def funcForSqrt(y: Double) : Double = x / y  // Note that x is not a parameter of funcForSqrt
    
       // Use the function fundForSqrt as a parameter of averageDamp
       fixedPoint(averageDamp(funcForSqrt))(1) 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多