2017-02-26 236 views
1

以下代碼有效,但我不太瞭解參數如何映射到參數列表。請注意我是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)

預先感謝您。

回答

2

這叫做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 

正如你看到的,只有一個參數列表出來的2個粘貼multiply的事實造成的第二個參數列表(這裏(y: Double))的新功能對於第一個參數列表(此處爲(5))具有固定的一組值。

寫這個,這或許將是您更明確的另一種等價的方式,如下:

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

在這裏,我們明確地用兩個參數列表應用功能,但使用通配符第二,這是一種告訴編譯器創建函數的函數,該函數用函數的參數替換下劃線。

+0

謝謝,現在我明白了。 – Eddie