在Scala中递归计算平方根

时间:2017-02-26 01:45:29

标签: scala recursion square-root

以下代码有效,但我不太清楚参数如何映射到参数列表。请注意我是Scala的新手。

import Math.abs

val tolerance = 0.0001
def isCloseEnough(x: Double, y: Double) =
  abs((x - y) / x) / x < tolerance

def fixedPoint(f: Double => Double)(firstGuess: Double) = {
  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) = (x + f(x)) / 2

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

sqrt(2.0)

上面sqrt函数的正文为fixedPoint(averageDamp(y => x / y))(1.0)

,其中

(y => x / y)映射到(f: Double => Double)函数的averageDamp

(1.0)映射到(firstGuess: Double)函数的fixedPoint,但

似乎没有映射到(x: Double)函数的averageDamp

提前谢谢。

1 个答案:

答案 0 :(得分:2)

这称为currying。真正发生的是averageDamp(y => x / y)被解释为函数:Double => Double,因为一旦将第一个参数列表设置为一组特定值,就会得到一个带有第二个参数列表的函数。 / p>

例如,请考虑以下代码:

def multiply(x: Double)(y: Double) = x * y

val multiplyByFive: Double => Double = multiply(5)
println(multiplyByFive(2)) // 10
println(multiplyByFive(6)) // 30

如您所见,将multiply仅应用于两个参数列表的事实创建了第二个参数列表(此处为(y: Double))的新函数,该列表具有一组固定的值第一个参数列表(这里是(5))。

另一种写这个的等效方式,可能会更加明确,如下:

val multiplyByFive: Double => Double = multiply(5)(_)

这里我们使用两个参数列表显式应用该函数,但是使用第二个通配符,这是一种告诉编译器创建一个函数的方法,该函数用函数的参数替换下划线。