解释递归和方法

时间:2020-06-27 03:40:15

标签: scala

我正在学习Scala编程。我在函数主题中。

def sumOfInts(a: Int, b: Int): Int = {
  if(a>b) 0 else a + sumOfInts(a+1,b)
}
println(sumOfInts(1,5) 

程序的输出为15,怎么可能是15?谁能解释一下它是如何得到15的?

2 个答案:

答案 0 :(得分:3)

让我们逐步了解调用它时会发生什么。

第一个sumOfInts用a = 1,b = 5调用。 a不超过b,因此我们使用分支a + sumOfInts(a+1,b)a是1,所以我们有1 + sumOfInts(2, 5)。按照这种模式,我们最终得到

1 + 2 + sumOfInts(3,5)
1 + 2 + 3 + sumOfInts(4,5)
1 + 2 + 3 + 4 + sumOfInts(5,5)
1 + 2 + 3 + 4 + 5 + sumOfInts(6, 5)

然后使用a=6a>b为真,因此sumOfInts(6,5)返回0。因此,最终的调用堆栈如下所示:

1 + 2 + 3 + 4 + 5 + 0

哪个给了我们15。

答案 1 :(得分:2)

我将以不太密集的方式放置行号,以便更轻松地引用它们

1: def sumOfInts(a: Int, b: Int) = {
2:  if (a > b) {
3:    0
4:  } else {
5:    a + sumOfInts(a+1, b)
6:  }
}

如果仔细观察,您会发现sumOfInts会自己调用-在第5行。此技术称为递归-您可能希望很好地理解它,因为它在许多算法和方法中都可以找到。和访谈问题:)但是简单地说,当函数进行一些计算时,递归会使用稍微修改的参数调用自身,然后将计算结果与自调用(称为递归调用)的结果“合并”。

在这种特殊情况下,所有这些“计算,递归,合并”都发生在第5行:

  • “计算”部分只是取a的值,
  • “递归”-呼叫sumOfInts(a+1, b)
  • “合并”是上述金额的总和。

现在,为了在某个时候真正完成,每个递归函数必须具有两个属性:

  • “您正在执行的函数”和递归调用之间的调用参数必须不同-在这种情况下,a+1会这样做,
  • 必须有一个条件才能终止递归-即应该有一个不会引起递归调用的代码路径。在这种情况下,这是第1行的条件

我认为理论足够:)让我们跟踪函数并查看结果。我将用“替代”函数来迭代调用-实际上,这实际上是编译器/运行时可用来优化代码的技术之一,但即使对于人类,它也是非常有用的:)

1st call: a=1, b=5, a < b => 1 + sumOfInts(1+1, 5)
2nd call: a=2, b=5, a < b => 1 + 2 + sumOfInts(2+1, 5)
3rd call: a=3, b=5, a < b => 1 + 2 + 3 + sumOfInts(3+1, 5)
4th call: a=4, b=5, a < b => 1 + 2 + 3 + 4 + sumOfInts(4+1, 5)
5th call: a=5, b=5, a = b => 1 + 2 + 3 + 4 + 5 + sumOfInts(5+1, 5)
6th call: a=6, b=5, a > b => 1 + 2 + 3 + 4 + 5 + 0 = 15