【问题标题】:Scala - Two functions sharing the second parameter listScala - 共享第二个参数列表的两个函数
【发布时间】:2017-07-16 06:05:02
【问题描述】:

我是 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 => x/y))(1)

我知道多亏了 Currying,Scala 让我们可以编写带有多个参数列表的函数。因此,对 fixedPoint 的调用将 avergaDamp 和 (1) 的结果作为参数传递,对我来说很清楚。

我不明白的是,当 averageDamp 本身位于第一个参数列表中时,它如何使用 fixedPoint 的第二个参数列表。我虽然那将是一个不同的范围,所以我期待的是:

fixedPoint(averageDamp(y => x/y)(1))(1)

Scala 的什么属性允许我们以这种方式实现柯里化?类似于隐式应用于参数列表的东西吗?

感谢您的宝贵时间

【问题讨论】:

    标签: scala currying


    【解决方案1】:

    这正是多个参数列表的工作方式:averageDamp(y =&gt; x/y) 等价于 z =&gt; averageDamp(y =&gt; x/y)(z),因此其类型为 Double =&gt; Double

    如果您按预期编写fixedPoint(averageDamp(y =&gt; x/y)(1))(1),则会出现类型不匹配,因为averageDamp(y =&gt; x/y)(1) 的类型为Double,而fixedPoint 需要Double =&gt; Double

    这里不相关。

    【讨论】:

      【解决方案2】:

      此行有效,因为在以下表达式中:

      fixedPoint(averageDamp(y => x/y))(1)
      

      函数“averageDamp(y => x/y)”是“按名称传递的”,即它在传递给函数“fixedPoint”时不会被评估,但会在从“fixedPoint”内部调用时被评估。

      值“(1)”只是传递给“fixedPoint”的参数“firstGuess”,它将提供给函数定义中的参数“guess”,如下表达式:

      val next = f(guess)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-01
        • 2015-12-13
        相关资源
        最近更新 更多