我在Worksheet中运行了下面的Scala代码:
package src.com.sudipta.week2.coursera
import scala.math.abs
import scala.annotation.tailrec
object FixedPoint {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val tolerance = 0.0001 //> tolerance : Double = 1.0E-4
def isCloseEnough(x: Double, y: Double): Boolean = {
abs((x - y) / x) / x < tolerance
} //> isCloseEnough: (x: Double, y: Double)Boolean
def fixedPoint(f: Double => Double)(firstGuess: Double): Double = {
@tailrec
def iterate(guess: Double): Double = {
val next = f(guess)
if (isCloseEnough(guess, next)) next
else iterate(next)
}
iterate(firstGuess)
} //> fixedPoint: (f: Double => Double)(firstGuess: Double)Double
def myFixedPoint = fixedPoint(x => 1 + x / 2)(1)//> myFixedPoint: => Double
myFixedPoint //> res0: Double = 1.999755859375
def squareRoot(x: Double) = fixedPoint(y => (y + x / y) / 2)(1)
//> squareRoot: (x: Double)Double
squareRoot(2) //> res1: Double = 1.4142135623746899
def calculateAverate(f: Double => Double)(x: Double) = (x + f(x)) / 2
//> calculateAverate: (f: Double => Double)(x: Double)Double
def myNewSquareRoot(x: Double): Double = fixedPoint(calculateAverate(y => x / y))(1)
//> myNewSquareRoot: (x: Double)Double
myNewSquareRoot(2) //> res2: Double = 1.4142135623746899
}
令我困惑的是:
这是什么?这是函数类型/函数定义还是我缺少这个术语? 基本上我怎么用英语解释这个功能?fixedPoint :( f:Double =&gt; Double)(firstGuess:Double)Double
calculateAverate:(f:Double =&gt; Double)(x:Double)Double
但它看起来我的函数的返回类型是Double,但我期待Double =&gt;双。原因是我将使用fixedPoint,它需要Double =&gt;双倍如下:
def myNewSquareRoot(x:Double):Double = fixedPoint(calculateAverate(y =&GT; x / y))(1)
请帮助我更清楚地了解高阶函数/ Currying。提前谢谢。
答案 0 :(得分:4)
fixedPoint: (f: Double => Double)(firstGuess: Double)Double
这里的任务是找到功能的固定点,任务的应用将是我们众所周知的平方根与牛顿方法
牛顿方法的平方根:
Calculates the square root of parameter x
def sqrt(x: Double): Double = ...
实现这一目标的经典方法是使用牛顿方法的连续近似。
计算sqrt(x):
示例:x=2
Estimation Quotient Mean
1 2/1=2 1.5
1.5 2/1.5=1.333 1.4167
1.4167 2/1.4167=1.4118 1.4142
1.4142 so on
首先,定义一个计算一个迭代步骤的函数
def sqrtIter(guess: Double, x: Double): Double =
if (isGoodEnough(guess, x)) guess
else sqrtIter(improve(guess, x), x)
第二次,定义一个改进的函数以改进估计和一个检查终止的测试:
def improve(guess: Double, x: Double) =
(guess + x / guess) / 2
def isGoodEnough(guess: Double, x: Double) =
abs(guess * guess - x) < 0.001
第三次,定义sqrt函数:
def sqrt(x: Double) = srqtIter(1.0, x)
使用您的固定点功能我们还计算数字的平方根
首先看看什么是定点:
如果number x
f(x) = x
被称为函数的固定点
对于某些函数,我们可以通过从初始估计开始,然后以重复方式应用f来定位固定点。
x, f(x), f(f(x))
这导致以下用于查找固定点的功能:
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)
}
在这个公式中,fixedPoint
是一个返回另一个函数的函数,即专用函数iterate
此处fixedPoint
def fixedPoint(f: Double => Double)(firstGuess: Double)
函数fixedPoint
应用于函数f: Double => Double
。所结果的
然后将函数应用于第二个参数
(firstGuess: Double)
这种表示法是可行的,因为函数应用程序关联到左侧。那是,
如果args1和args2是参数列表,那么f(args1)(args2)
相当于(f(args1))args2
在你的程序中,第一个参数是函数,其中输入类型为Double,返回类型为Double,然后将此函数应用于猜测
重新定义平方根函数。
让我们从sqrt的规范开始:
sqrt(x) = the y such that y*y = x
= the y such that y = x / y
因此,sqrt(x)是函数y => x / y
的固定点。这表明
sqrt(x)
可以通过定点迭代计算:
def sqrt(x: double) = fixedPoint(y => x / y)(1.0)
这是一个很长的答案,但我认为这将有助于您理解这个概念
答案 1 :(得分:2)
功能
def fixedPoint (f: Double => Double)(firstGuess: Double):Double
是一个函数定义,它有两个参数:
Double
类型的参数,该参数返回Double
和Double
值并返回Double
。将单个参数分离到它们自己的括号组允许该函数用于currying:
def mySqrtCalc(x:Double)(firstGuess:Double):Double = {...}
val mySqrtFunc = mySqrtCalc(2.0) _
val v = mySqrtFunc(1) // parameter firstGuess is set to 1
除了currying的能力,这相当于未经证实的版本
def fixedPoint (f: Double => Double,firstGuess: Double):Double
对你来说可能更熟悉。
calculateAverate
的结果是一个Double,因为你将传递函数f的结果加到带x的x,它给你一个Double
,因为f是一个函数Double => Double
您在calculateAverate
方法体中以咖喱方式使用myNewSquareRoot
方法,首先只给出两个参数中的第一个,省略第二个参数,这是从外部获取的fixedPoint
方法。省略calculateAverate
的第二个参数会为您提供Double=>Double
方法所需的方法fixedPoint
。
您可以插入一些println(s"<methodname> value=$value")
来观察执行流程并理解方法调用顺序。