特定の質問に答えるには:いいえ、言語を学習する観点からすると、再帰は機能ではありません。教授が本当に教えていない「機能」を使用するためにあなたのマークを本当にドッキングした場合、それは間違っていました。
行間を読むと、1つの可能性として、再帰を使用することで、彼のコースの学習結果となるはずの機能の使用を回避できた可能性があります。たとえば、反復をまったく使用しなかった場合や、およびのfor
両方for
を使用する代わりにループのみを使用した場合などwhile
です。課題は特定のことを実行する能力をテストすることを目的としていることが一般的であり、それらを実行しない場合、教授はその機能のために取っておいたマークを付与することはできません。ただし、それが本当に失点の原因だった場合、教授はこれを自分自身の学習体験としてとらえる必要があります。特定の学習成果を示すことが課題の基準の1つである場合は、生徒に明確に説明する必要があります。 。
そうは言っても、ここでの再帰よりも反復の方が良い選択であるという他のコメントや回答のほとんどには同意します。いくつかの理由があり、他の人々がある程度それらに触れたが、彼らが彼らの背後にある考えを完全に説明したとは思えない。
スタックオーバーフロー
より明白なのは、スタックオーバーフローエラーが発生するリスクがあることです。実際には、ユーザーが実際にスタックオーバーフローをトリガーするために何度も誤った入力を行わなければならないため、作成したメソッドが実際に1につながる可能性はほとんどありません。
ただし、注意すべき点の1つは、メソッド自体だけでなく、呼び出しチェーン内の上位または下位の他のメソッドがスタックに存在することです。このため、利用可能なスタックスペースをさりげなく取得することは、どの方法でもかなり失礼です。他のコードが不必要に多くのコードを使い果たしてしまうリスクがあるため、コードを作成するときはいつでも、空きスタック領域について常に心配する必要はありません。
これは、抽象化と呼ばれるソフトウェア設計のより一般的な原則の一部です。本質的に、を呼び出すときDoThing()
、気にする必要があるのは、事が行われたことだけです。実装方法の詳細について心配する必要はありません。しかし、スタックの貪欲な使用はこの原則を破ります。コードのすべてのビットは、コールチェーンの他の場所のコードによって残されたと想定できるスタックの量を心配する必要があるためです。
読みやすさ
他の理由は読みやすさです。コードが目指すべき理想は、人間が読める形式のドキュメントになることです。この場合、各行はコードが何をしているかを簡単に説明します。次の2つの方法を使用します。
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();
}
はい、どちらも機能し、どちらも非常に理解しやすいです。しかし、2つのアプローチはどのようにして英語で記述できるでしょうか。私はそれが次のようなものになると思います:
入力が有効になるまで入力を求め、それを返す
対
入力を要求し、入力が有効な場合はそれを返し、それ以外の場合は入力を取得してその結果を返します
おそらく、後者については少し不格好な表現を考えることもできますが、最初の表現は、実際に何をしようとしているのか、概念的にはより正確な説明になるといつも思うでしょう。これは、再帰が常に読みにくくなると言っているのではありません。ツリートラバーサルのように、それが輝く状況では、再帰と別のアプローチの間で同じ種類の並列分析を行うことができ、再帰が行ごとに、より明確に自己記述的なコードを与えることがほぼ確実にわかります。
単独では、これらはどちらも小さな点です。スタックオーバーフローが実際に発生する可能性はほとんどなく、可読性の向上はわずかです。しかし、どのプログラムもこれらの小さな決定の多くのコレクションになるので、孤立していてもそれほど重要ではない場合でも、正しい決定の背後にある原則を学ぶことが重要です。