5

テール再帰のほかにテールコールの最適化は可能ですか?私は、再帰を伴わないが、成功していないものを見つけようと試みてきた。出来ますか?どんな例?テール再帰のほかにテールコールの最適化?

+0

[継続は(http://en.wikipedia.org/wiki/Continuation -passing_style "ウィキペディアの記事「Continuation-passing style」)は、テールコールの最適化の対象となる可能性があります。 – stakx

答えて

1
int bar(int x); 
int foo(int x) { return bar(x); } 

foo単に直接呼び出し元に戻りますbarにジャンプすることができます。どこでも再帰は必要ありません。

+0

しかし、この単純なインライン展開ではありませんか? – dtech

+0

@ddriver:私はちょうどその宣言だけを残して、 'バー'の定義を取り出しました。その定義なしで 'bar'をインライン化することはできませんが、呼び出し側で末尾呼び出しの最適化を実行できます。違いを見ます? – Mehrdad

+0

これは実際に潜在的に相互に再帰的な関数のペアの半分です... –

3

確かに「テールコール最適化」は、この種の最適化のための最も一般的な、再帰的に不可知な形式の用語です。この最適化は、再帰を、whileループまたはそれに類するものと同等のものに置き換えません。代わりに、テールコールは、呼び出し元のスタックフレームが再利用されるように変換されます。 の形式のコードreturn f(...)またはf(...); returnはこれに修正可能です。コンパイラが何が呼び出されているかをコンパイラが知ることができないファンクションポインタ/クロージャ/仮想メソッドの場合でも、のいずれかの場合はfで動作します。したがって、別のコンパイル、高次関数、レイトバインドなどでもうまく機能します。

十分なコードを見れば、それは機能的にも必須でもありません。一般的なケースは、呼び出し元が主タスクの呼び出し先に委任し、いくつかの追加の準備だけです。関数コードでは、たった一つだけしかなく、他の小さな関数の観点から実装されている小さな関数がたくさんあるので、単純な変換を引数に適用したいくつかの層で終わります。次の層(変換されたデータを引数として) TCOは2番目のステップを最適化します(理想的には)単純なjumpのような安価な呼び出しを行い、モノリシックな実装よりもスタックスペースを少なくして素敵なモジュラーコードにします。

SomeClass doSomething(Argument a) { 
    log.debug("Doing something"); 
    return this.somethingDoer.doIt(a, this.someExtraData); 
} 

技術的に相互に再帰的だが、通常は数十人との任意の機能の非常に少数のアクティベーションを(持っているもう一つの例:あなたが他のオブジェクトのオブジェクトを構成し、そのデリゲート便利なメソッドを公開することがあり、オブジェクト指向設計ではまたはその間の他のアクティベーション数百)、状態ごとの機能を有し、その状態に入るようにそれを呼び出すことによって実装された状態機械である:

void stateA() { 
    // do actual work 
    // determine which transition applies 
    stateB(); 
} 

void stateB() { 
    // do actual work 
    // determine which transition applies 
    state...(); 
} 

// dozens, possibly hundreds of other states 
関連する問題