我是Scala的新手,我遇到了一个我希望有人可以解释我的情况。
在观看Martin Odersky的课程时,我发现他使用以下脚本来解释返回函数的函数
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(x => 1 + x/2)(1)
def averageDamp(f: Double => Double)(x: Double) = (x + f(x))/2
def sqrt(x : Double) = fixedPoint(averageDamp(y => x/y))(1)
sqrt(2)
我完全理解脚本是如何工作的,但我没想到这一行:
fixedPoint(averageDamp(y =&gt; x / y))(1)
我知道感谢Currying,Scala让我们用几个参数列表编写函数。因此,对 fixedPoint 的调用作为参数传递 avergaDamp 和(1)的结果对我来说很清楚。
我不明白的是 averageDamp 在第一个参数列表中使用 fixedPoint 的第二个参数列表时。我认为这是一个不同的范围,所以我期待的是:
fixedPoint( averageDamp(y =&gt; x / y)(1))(1)
Scala的属性是什么允许我们以这种方式实现currying?是否类似于隐式应用于参数列表?
感谢您的时间
答案 0 :(得分:2)
这就是多个参数列表的工作原理:averageDamp(y => x/y)
等同于z => averageDamp(y => x/y)(z)
,因此其类型为Double => Double
。
如果您按预期编写fixedPoint(averageDamp(y => x/y)(1))(1)
,则会出现类型不匹配,因为averageDamp(y => x/y)(1)
类型为Double
而fixedPoint
需要Double => Double
。
隐含与此无关。
答案 1 :(得分:2)
此行有效,因为在以下表达式中:
fixedPoint(averageDamp(y => x/y))(1)
函数“averageDamp(y =&gt; x / y)”是“按名称传递”,即在传递给函数“fixedPoint”时不会对其进行求值,但在从“fixedPoint”内部调用时将对其进行求值。 / p>
value“(1)”只是传递给“fixedPoint”的参数“firstGuess”,它将在下面的表达式中提供给函数定义中的参数“guess”:
val next = f(guess)