Scala - 共享第二个参数列表的两个函数

时间:2017-07-16 06:05:02

标签: scala currying

我是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?是否类似于隐式应用于参数列表?

感谢您的时间

2 个答案:

答案 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)类型为DoublefixedPoint需要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)