要回答您的特定问题:不,从学习语言的角度来看,递归不是功能。如果您的教授真的停靠了您,则使用了他尚未教过的“功能”,这是错误的。
在两行之间阅读时,一种可能性是通过使用递归,您避免使用曾经被认为是其课程学习成果的功能。例如,也许您根本不使用迭代,或者您仅使用for
循环而不是同时使用for
和while
。通常,一项任务旨在测试您做某些事情的能力,如果您避免做这些事情,您的教授根本无法授予您为此功能留出的分数。但是,如果这确实是造成您丢分的原因,则教授应将其视为自己的学习经历-如果证明某些学习成果是作业的标准之一,则应向学生明确说明。
话虽如此,我同意其他大多数意见和答案,认为迭代是比递归更好的选择。原因有两个,虽然其他人在某种程度上已经涉及到它们,但我不确定他们是否已经完全解释了它们背后的想法。
堆栈溢出
更为明显的是,您可能会遇到堆栈溢出错误。实际上,您编写的方法不太可能真正导致错误,因为用户必须多次输入错误才能实际触发堆栈溢出。
但是,要记住的一件事是,不仅方法本身,而且调用链中位于上位或下位的其他方法都将位于堆栈中。因此,随便吞噬可用的堆栈空间对于任何方法都非常不礼貌。没人愿意在每次编写代码时都经常担心可用的堆栈空间,这是因为其他代码可能会不必要地消耗掉其中的大量内存。
这是称为抽象的软件设计中更通用的原理的一部分。本质上,当您致电时DoThing()
,您需要关心的只是事情已经完成。你不应该约的实现细节担心如何,它的完成。但是贪婪地使用堆栈会破坏这一原理,因为每一位代码都必须担心调用链中其他地方的代码可以安全地假定有多少堆栈留给了它。
可读性
另一个原因是可读性。代码应该向往的理想是成为人类可读的文档,其中每一行都简单地描述了它在做什么。采取以下两种方法:
private int getInput() {
int input;
do {
input = promptForInput();
} while (!inputIsValid(input))
return input;
}
与
private int getInput() {
int input = promptForInput();
if(inputIsValid(input)) {
return input;
}
return getInput();
}
是的,它们都可以使用,是的,它们都很容易理解。但是如何用英语描述这两种方法?我认为应该是这样的:
我将提示您输入,直到输入有效,然后将其返回
与
我将提示输入,然后如果输入有效,则将其返回,否则将获取输入并返回该结果
也许您会想到后者的措辞稍微不那么笨拙,但我认为您总是会发现第一个在概念上将对您实际要执行的操作进行更准确的描述。这并不是说递归总是不太可读。对于闪耀的情况(例如遍历树),您可以在递归和另一种方法之间进行相同类型的并排分析,并且几乎可以肯定的是,递归提供的代码逐行清晰易懂。
孤立地看,这两个都是小问题。这极不可能真的导致堆栈溢出,并且可读性的提高很小。但是任何程序都将包含许多这些小决定,因此即使孤立地将它们无关紧要,重要的是要学习使它们正确的背后原理。