【发布时间】:2021-11-23 13:53:03
【问题描述】:
我正在尝试使用尾递归创建毕达哥拉斯三元组,但即使我没有在 return 语句中进行任何计算,编译器似乎也无法识别它。
错误代码是这样的:Cannot rewrite recursive call: it is not in tail position
这是尾递归的代码:
def tailPythagorean(positiveNumber: Int): List[(Int, Int, Int)] = {
return tailRunner(positiveNumber, positiveNumber, List())
.take(positiveNumber);
}
@tailrec def tailRunner(biggerNumber: Int, smallerNumber: Int, list: List[(Int, Int, Int)]): List[(Int, Int, Int)] = {
if (biggerNumber == 0 || smallerNumber == 0) {
return list;
}
val smallNumber = if (smallerNumber == 1) biggerNumber - 1 else smallerNumber - 1;
return tailRunner(biggerNumber, smallNumber, List((((biggerNumber + 1) * (biggerNumber + 1) - (smallerNumber * smallerNumber)), (2 * (biggerNumber + 1) * smallerNumber), ((biggerNumber + 1) * (biggerNumber + 1) + (smallerNumber * smallerNumber)))) ::: list);
}
这里是未针对尾递归优化的递归解决方案的代码(供参考):
def recursivePythagorean(positiveNumber: Int): List[(Int, Int, Int)] = {
return recursiveRunner(positiveNumber, positiveNumber)
.take(positiveNumber);
}
def recursiveRunner(biggerNumber: Int, smallerNumber: Int): List[(Int, Int, Int)] = {
if (biggerNumber == 0 || smallerNumber == 0) {
return List();
}
if (smallerNumber == 1) {
return recursiveRunner(biggerNumber - 1, biggerNumber - 1) ::: List((((biggerNumber + 1) * (biggerNumber + 1) - (smallerNumber * smallerNumber)), (2 * (biggerNumber + 1) * smallerNumber), ((biggerNumber + 1) * (biggerNumber + 1) + (smallerNumber * smallerNumber))));
}
else {
return recursiveRunner(biggerNumber, smallerNumber - 1) ::: List((((biggerNumber + 1) * (biggerNumber + 1) - (smallerNumber * smallerNumber)), (2 * (biggerNumber + 1) * smallerNumber), ((biggerNumber + 1) * (biggerNumber + 1) + (smallerNumber * smallerNumber))));
}
}
编辑:根据@AminMal 和@Jörg W Mittag 的cmets,确实是return 关键字的存在使编译器抱怨。删除它们为我修复了它:
def tailPythagorean(positiveNumber: Int): List[(Int, Int, Int)] = {
tailRunner(positiveNumber, positiveNumber, List())
.take(positiveNumber);
}
@tailrec def tailRunner(biggerNumber: Int, smallerNumber: Int, list: List[(Int, Int, Int)]): List[(Int, Int, Int)] = {
if (biggerNumber == 0 || smallerNumber == 0) {
return list;
}
if (smallerNumber == 1) {
tailRunner(biggerNumber - 1, biggerNumber - 1, List((((biggerNumber + 1) * (biggerNumber + 1) - (smallerNumber * smallerNumber)), (2 * (biggerNumber + 1) * smallerNumber), ((biggerNumber + 1) * (biggerNumber + 1) + (smallerNumber * smallerNumber)))) ::: list);
}
else {
tailRunner(biggerNumber, smallerNumber - 1, List((((biggerNumber + 1) * (biggerNumber + 1) - (smallerNumber * smallerNumber)), (2 * (biggerNumber + 1) * smallerNumber), ((biggerNumber + 1) * (biggerNumber + 1) + (smallerNumber * smallerNumber)))) ::: list);
}
}
【问题讨论】:
-
尝试将tailrec函数的最后两行放在else块中,另外,最好不要使用return关键字,你不是必须这样做:)
-
您的 tailrec 代码为我编译没有错误(Scala 2.13.3)。顺便说一句,经验丰富的 Scala 程序员永远不会,永远,使用
return。 Here's why. -
另外,
tailRunner()不是recursiveRunner()算法的准确实现:biggerNumber实际上从未递减。 -
很好地抓住了逻辑错误@jwvh!根据this answer,我认为它为您编译没有错误,因为@tailrec 标志是在 Scala 2.8 中提出的
标签: scala recursion tail-recursion scala-3 pythagorean