【问题标题】:Scala Tail RecursionScala尾递归
【发布时间】:2018-03-08 12:32:15
【问题描述】:

所以我有这个递归函数,可以将两个数字相乘,很简单。

    def mul(n: Int, m: Int):Int =
        if(m > 1) n + mul(n, dec(m))
        else n

现在我试图把它变成一个尾递归函数,我试过这个:

    def mulWithTail(n: Int, m: Int):Int = {
        @tailrec
        def iter(result: Int, x: Int):Int =
            if(x == 0) result
            else result + iter(result, dec(x))
        iter(n, m)
    }

但是我得到以下错误:

错误:无法优化 @tailrec 注释方法 iter:它包含 一个不在尾部位置的递归调用

else result + iter(result, dec(x))

问题:你能解释一下为什么会出现这个错误吗?我应该如何重构我的代码?

【问题讨论】:

  • dec() 只是顺便减一

标签: scala recursion


【解决方案1】:

你可以让你的函数尾递归简单地添加一个额外的参数,就像一个累加器。像这样。

def mul(n: Int, m: Int, acc: Int): Int =
  if (m > 1) mul(n, m - 1, n + acc)
  else acc

要使函数尾递归,您不能在递归步骤中执行任何其他操作,而是递归调用函数。在您的代码示例中,您正在递归步骤中执行加法。

  • n + mul(n, dec(m))

  • result + iter(result, dec(x))

【讨论】:

  • 你能解释一下添加这个额外的参数是如何使它成为尾递归的吗?
  • 当然。已编辑以包含解释。
  • @PhillipR:在这种情况下,中缀运算符会混淆事物。拿一张纸,用纯函数调用符号写下递归调用,你会立即看到递归调用不在尾部位置:plus(result, iter(result, dec(x)))。在这里,很明显对iter 的调用包含在对plus 的调用中,因此不是最后一次执行的调用。
猜你喜欢
  • 2018-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多