【问题标题】:Tail-Recursive Function (Coursera Issues)尾递归函数(Coursera 问题)
【发布时间】:2015-06-22 00:06:59
【问题描述】:

我正在学习有关 Scala 函数式编程的 Coursera 课程,以便学习该语言。

他们引入了尾递归函数的概念,并将它们基本上定义为以调用自身结束的函数。但随后他们将此作为工作示例:

def sum(f: Int => Int)(a: Int, b: Int): Int = {
  def loop(a: Int, acc: Int): Int = {
    if (a > b) acc
    else loop(a + 1, f(a) + acc)
  }
  loop(a, 0)
}

如果我用 @tailrec 注释 sum,我会收到错误,因为 IDE (IntelliJ) 不认为它是尾递归的。

sum 在这里被称为尾递归,还是内部实现“循环”在这种情况下被认为是尾递归?

【问题讨论】:

    标签: scala syntax tail-recursion higher-order-functions


    【解决方案1】:

    你是对的。 sum 需要调用自己,否则 Scala 会抱怨:

    @tailrec annotated method contains no recursive calls
    

    如果你告诉编译器它到底在哪里,通过将 @tailrec 移动到尾递归所在的位置:

    def sum(f: Int => Int)(a: Int, b: Int): Int = {
      @tailrec def loop(a: Int, acc: Int): Int = {
        if (a > b) acc
        else loop(a + 1, f(a) + acc)
      }
      loop(a, 0)
    }
    

    然后编译器会满意它是尾递归优化的。

    【讨论】:

      【解决方案2】:

      内部loop 方法是尾递归的,sum 方法根本不是递归的。因此,您应该使用@tailrec 注释loop

      loop 移到外部范围可能有助于可视化正在发生的事情:

      def sum(f: Int => Int)(a: Int, b: Int): Int = {
          loop(a, 0)
      }
      
      def loop(a: Int, acc: Int): Int = {
          if (a > b) acc
          else loop(a + 1, f(a) + acc)
      }
      

      如您所见,sum 只是loop 的公共入口点。

      (请注意,上面的代码不会编译,因为loop 不再关闭bf,但你明白了。)

      【讨论】:

        猜你喜欢
        • 2011-12-10
        • 1970-01-01
        • 2019-09-14
        • 2015-01-27
        • 1970-01-01
        • 1970-01-01
        • 2016-01-06
        • 2020-09-16
        • 2011-05-28
        相关资源
        最近更新 更多