2015-01-01 2 views
0

, пожалуйста, найдите фрагмент кода из онлайн-курса Coursera (лекция 2.3) по функциональному программированию в Scala.Оценка функциональных параметров в Scala (функциональное программирование)

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)           

} 

Несколько пунктов заблокировали меня, когда я пытаюсь понять этот фрагмент кода.

Хотелось бы вам помочь в понимании этого кода.

2 очка, что раздражает меня являются: - когда вы звоните averageDamp, есть 2 параметра «х» и «у» в функции передается (например averageDamp(y => x/y).), Но вы никогда не указать «у» параметра в определение усредненной функции (например, def averageDamp(f: Double => Double)(x: Double): Double = (x + f(x))/2). Где и как компилятор scala оценивает параметр «y». - второй момент может быть связан с первым, я не знаю, на самом деле. Когда я вызываю функцию averageDamp, я передаю только параметр функции f (например, y => x/y), но я не передаю второй параметр функции, который является «x» (например, (x: Double) второй параметр). Как компилятор scala оценивает параметр «x» в этом случае, чтобы отобразить результат вызова averageDamp.

Я думаю, что я что-то пропустил для оценки или замены модели scala и функционального программирования.

Спасибо за помощь и новый год!

Эрве

ответ

2

1) Вы не пройти x и y параметр как f, вы передаете функцию. Функция определена как y => x/y, где y является просто заполнителем для аргумента этой функции, тогда как x является фиксированным значением в этом контексте, поскольку оно дается как аргумент для метода sqrt (в примере x равно 2). Вместо того, чтобы фантазии лямбда-синтаксис, вы не могли бы написать, а

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 => 2 + y

+0

ок, спасибо, я думаю, что это делает мой разум ясным. Если я переформулирую ваш ответ с помощью Грегора Раймана.Я бы сказал, что моя функция averageDamp передается вызывающей функции fixedPoint и используется линией 'val next = f (guess)'. guess - параметр y, который я искал в 'y => x/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) 
}