末尾再帰(まつびさいき)とは、再帰的な関数やプロシージャにおいて、自身の再帰呼び出しが、その計算における最後のステップになっているような再帰のパターンのことである。呼び出しではなく、戻り先を保存しないジャンプに最適化できるという特徴がある(#末尾呼出し最適化)。手続き型言語と末尾再帰[編集]C言語のような副作用と構造化を基本とする手続き型言語では、言語処理系による自動的な末尾呼び出しへの変換やその最適化(末尾最適化)は難しい。自己再帰を注意して書けば、最適化によりループにできるコンパイラもある、という程度である。プログラムの手動変換[編集]一般に手続き型言語では、サブルーチン呼び出しのたびにスタックに呼び出し先から戻るための情報を保存する。そのため再帰が深くなりすぎるとスタックオーバーフローでプログラムが異常終了する。そのような場合、次のようにループに変換して回避する。Pの中に最低1個のreturn文がないとスタックオーバーフローあるいは無限ループになる*/関数型言語と末尾再帰[編集]関数型言語では、自身の戻り値に別の関数の戻り値を使うという末尾呼び出しによるプログラミングは自然なスタイルである。tail-recursive)。関数型言語の処理系には、プログラム全体を継続渡しスタイルに変換し、全ての呼び出しを末尾呼び出しに変換する手法もある。置き換えモデルを基準に考えれば、ある手続きが返す値はその中で最後に呼び出した手続きの結果に等しく、それ以外の部分は過程の分岐または副作用をもつ場合のみ意味を持つ。従って上記関数的な観点では手続きの末尾だけを考慮すればよく、ここで再帰が行われる場合を末尾再帰という。1末尾行では定義と同型の式が現れている。optimization)とは、末尾呼出しのコードを、戻り先を保存しないジャンプに変換することによって、スタックの累積を無くし、効率の向上などを図る手法である。elimination)などとも言う。関数呼出しでは、呼出し毎にスタックに呼出し元に戻るための情報を保存する。これをジャンプに最適化できれば、みかけの再帰がいくら深くなってもスタックが溢れたりすることがなくなる。この最適化が言語処理系によって行われるのであれば、プログラマが再帰的な手続きをループに変換することなく記述しても、再帰のためのスタック溢れを気にかける必要が無くなる。理論的には、継続渡しによるgotoと同等のジャンプ処理では、手続きの呼出し元の情報を保存する必要がないことに帰着する。この場合returnはgotoの特殊なケースで、ジャンプ先が呼出し元に等しいケースである。末尾最適化があれば、手続きの再帰を行なう時でも、結果はループと等価な処理手順となり、どれほど深い再帰を行なってもスタックオーバーフローを起こさない。このような振る舞いは「正しい終端再帰」と呼ばれる。Schemeは実装仕様として正しい終端再帰を要求する言語である。Schemeに限らず、一部Cコンパイラなどでも条件がそろえば、再帰呼び出しが最適化される事がある。(日時は個人設定で未設定ならばUTC)。表示-継承ライセンスの下で利用可能です。追加の条件が適用される場合があります。詳細は利用規約を参照してください。Cookieに関する声明モバイルビュ。