1

元の言葉は

プロセスとプロシージャの区別がわかりにくい理由の 1 つは、一般的な言語 (Ada、Pascal、C を含む) のほとんどの実装が、再帰プロシージャの解釈でメモリ量が消費され、そのメモリ量が再帰プロシージャとともに増加するように設計されていることです。記述されたプロセスが原則として反復的である場合でも、プロシージャ コールの数。結果として、これらの言語は、do、repeat、until、for、while などの特別な目的の「ループ構造」に頼ることによってのみ、反復プロセスを記述できます。

C 言語に詳しくないのですが、Java や C# はどうですか? これは彼らにも当てはまりますか?なぜ?

注: 著者はさまざまな言語の能力について話していると思いました。しかし実際には、コンパイラの実装が異なるだけです。

4

4 に答える 4

3

C (および同様の言語) は通常、コール スタックを使用して、各関数にローカルな変数を格納します。関数が呼び出されるたびに、スタックが占有されます。関数が戻るたびに、スタックの使用量が減少します。

ただし、スマート コンパイラが必要に応じて末尾呼び出しの最適化などを実行できないわけではありません。したがって、スタックの使用が排除されます。Lisp のような言語では、インタプリタはそのような最適化を実行する必要があると思います。

于 2012-07-21T15:52:29.123 に答える
2

彼は基本的に、これらの言語のコンパイラは末尾再帰の削除を実行できないと言いたいのです。長い話を短くするために、彼は間違っています (またはとにかく過度に一般化します。「ほとんどの実装」はイタチの言い回しで十分であり、技術的には正しいかもしれませんが、せいぜい誤解を招く可能性があります)。他のすべての言語のすべてのコンパイラが末尾再帰の除去を行うことを保証することはできませんが、少なくとも一部の C および C++ コンパイラ (Intel C++、gcc/g++ など) が可能であり、そうすることに疑問の余地はありません。私は確認していませんが、GNAT (Gnu Ada コンパイラー) が C や C++ コンパイラーなどと同じオプティマイザーを使用していることを考えると、末尾再帰の除去も実行できるとすぐに推測できます。

私が Pascal を使い始めてからかなり時間が経ちましたので、それについて賢明なコメントをすることはできません。私の当面の推測では「いいえ」ですが、それは言語自体とはほとんど関係がなく、ほとんどの場合、事実に帰着します。現在の Pascal の使用は Borland にさかのぼり、最適なコード生成に多くの労力を費やしたようには見えませんでした。

于 2012-07-21T15:52:42.560 に答える
1

あなたは尋ねました: C# はどうですか?

C# は、Java と同様ですが、ほとんどの C/C++ または ADA 実装とは異なり、中間言語にコンパイルされます。その後、通常は実行時に「ジャスト イン タイム コンパイラ」によってさらにコンパイルされます。

執筆時点では、C# コンパイラは末尾再帰の削除を実行しませんが、JIT は可能です。

詳細については、http://blogs.msdn.com/b/clrcodegeneration/archive/2009/05/11/tail-call-improvements-in-net-framework-4.aspxを参照してください。

于 2012-07-21T17:12:19.217 に答える
0

コンパイラの実装とは関係ありません。

あなたは彼が言おうとしている、プロセスと手順の区別というまさにその点を見落としています。手順が実装している基本的なプロセスが原則として反復的であっても、手順が再帰的である場合があります。再帰的手続きはスタックを消費します。

于 2012-07-22T02:15:10.533 に答える