再帰関数を常に反復関数に変えることはできますか? はい、もちろんです。記憶が役に立つなら、教会とチューリングのテーゼがそれを証明しています。簡単に言えば、再帰関数によって計算可能なものは、反復モデル (チューリング マシンなど) によって計算可能であり、その逆も同様であると述べています。この論文は、変換を行う方法を正確に示しているわけではありませんが、確実に可能であると述べています。
多くの場合、再帰関数の変換は簡単です。Knuth は、「The Art of Computer Programming」でいくつかのテクニックを提供しています。多くの場合、再帰的に計算されたものは、まったく異なるアプローチでより少ない時間とスペースで計算できます。この古典的な例は、フィボナッチ数またはその数列です。学位取得計画でこの問題に確実に対応しています。
このコインの裏返しとして、式の再帰的な定義を以前の結果をメモ化するための招待状として扱うほど高度なプログラミング システムを想像することができます。これにより、コンピューターにどのステップを実行するかを正確に伝える手間をかけずに速度の利点が提供されます。再帰的な定義を持つ数式の計算に従います。ダイクストラがそのようなシステムを想像したことはほぼ間違いありません。彼は、プログラミング言語のセマンティクスから実装を切り離すことに長い時間を費やしました。繰り返しになりますが、彼の非決定論的マルチプロセッシング プログラミング言語は、実際のプロ プログラマーよりもはるかに優れています。
最終的な分析では、多くの関数は単純に理解しやすく、読みやすく、再帰的な形式で書きやすいということです。やむを得ない理由がない限り、これらの関数を (手動で) 明示的な反復アルゴリズムに変換しないでください。あなたのコンピュータはその仕事を正しく処理します。
説得力のある理由が 1 つあります。[アスベストの下着を着用する] Scheme、Lisp、Haskell、OCaml、Perl、または Pascal のような超高水準言語のプロトタイプ システムがあるとします。C または Java での実装が必要な状況があるとします。(おそらくそれは政治的なものです。)そうすれば、確かにいくつかの関数を再帰的に記述できますが、これを文字通りに翻訳すると、ランタイム システムが爆発します。たとえば、Scheme では無限末尾再帰が可能ですが、既存の C 環境では同じイディオムが問題を引き起こします。もう 1 つの例は、レキシカルにネストされた関数と静的スコープの使用です。これは Pascal ではサポートされていますが、C ではサポートされていません。
このような状況では、元の言語に対する政治的抵抗を克服しようとするかもしれません。Greenspun の (冗談めかした) 第 10 法則のように、Lisp の再実装がうまくいかないことに気付くかもしれません。または、ソリューションへのまったく異なるアプローチを見つけることもできます。しかし、いずれにせよ、必ず方法はあります。