在 Scala 中递归计算平方根

Calculating Square Root recursively in Scala

下面的代码可以工作,但我不太明白参数是如何映射到参数列表的。请注意我是 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) 映射到 averageDamp 函数的 (f: Double => Double)

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

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

提前致谢。

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

例如,考虑以下代码:

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)(_)

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