【问题标题】:Scala recursive implementation with Stream type具有 Stream 类型的 Scala 递归实现
【发布时间】:2020-12-27 05:07:56
【问题描述】:

我已经开始在 Coursera 上学习 Scala 并且有一些关于 squareRootGuess 实现的问题如下

我正在尝试实施标准来过滤sqrtGuess 定义中的准确猜测,如下所示,但它给了我堆栈溢出错误。

def sqrtGuess(x: Double): Stream[Double] = { 
  def nextGuess(guess: Double): Double = (guess + x / guess)/2

  def isSufficient(guess: Double): Boolean = math.abs(x - guess*guess)/x < 0.001

  def guesses: Stream[Double] = 
    1 #:: guesses.map(nextGuess).filter(isSufficient)

  guesses
}

但如果我们在 sqrtGuess 之外定义 isSufficient 并将其应用于 sqrtGuess 流,则效果很好。

def sqrtGuess(x: Double): Stream[Double] = { 
    def nextGuess(guess: Double): Double = (guess + x / guess)/2
    def guesses: Stream[Double] = 
        1 #:: guesses.map(nextGuess)
    guesses
}

def isSufficient(guess: Double, x: Double): Boolean = math.abs(x - guess*guess)/x < 0.001

sqrtGuess(4.2).filter(isSufficient(_, 4.2)).take(10).toList

我想知道sqrtGuess 的第一个实现会发生什么?我正在尝试使用替换模型来证明它,但它似乎没有任何问题。

【问题讨论】:

    标签: scala recursion scala-streams


    【解决方案1】:

    我假设您使用的是 Scala 2.12,因为 Stream 在 Scala 2.13 中已弃用,并带有以下弃用消息:

    使用 LazyList(完全惰性)而不是 Stream(只有惰性尾部)

    我没有真正的证据证明我要说的话,但我可以假设这是正在发生的事情:

    在非工作示例中,您尝试根据x = 4.2guess = 1.0 生成一个列表。计算的下一个元素被过滤器删除。所以下一个不会添加到流中。因此,guesses 总是无法为流创建新元素,而且我们永远不会在流中达到 10 个元素。栈溢出是由于无限递归造成的。

    为了过滤,你需要先创建流,并对其进行过滤:

    def sqrtGuess1(x: Double): Stream[Double] = {
      def nextGuess(guess: Double): Double = (guess + x / guess)/2
    
      def isSufficient(guess: Double): Boolean = math.abs(x - guess*guess)/x < 0.001
    
      def guesses: Stream[Double] =
        1 #:: guesses.map(nextGuess)
    
      guesses.filter(isSufficient)
    }
    

    【讨论】:

    • 谢谢它的工作!就像你说的那样是scala 2.12版,因为我正在学习的课程是老课程哈哈。
    猜你喜欢
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多