2009-08-02 16 views
1

私はその実装で再帰を使用するいくつかのコードを持っています。 profiler which I'm usingは再帰関数呼び出しではうまくいかないので、再帰的でないように書き直したいと思います。再帰を避ける

void Parse(Foo foo) 
{ 
    A() 
    for (;;) 
    { 
    B(); 
    if (C()) 
     return; 
    if (D()) 
    { 
     Run(); 
    } 
    E(); 
    } 
} 

void Run() 
{ 
    X(); 
    if (Y()) 
    { 
    Parse(); 
    } 
    Z(); 
} 

上記で擬似コード:

現在のコードは次のようなものです。文字A、B、C、D、E、X、Y、Zはメソッドであり、Parse()とRun()も同様です。わかりやすくするために、私はさまざまなパラメータとオブジェクトの逆参照を除外しました(たとえば、Runはオブジェクトインスタンスのメソッドであり、いくつかのパラメータが必要です)。

とにかく、私の質問は、これを非再帰的コードにするにはどうすればいいですか?

同等の非再帰的コードがあることを私には思える:

void Parse(Foo foo) 
{ 
    //create a local stack variable to emulate recursion 
    Stack<Foo> foos = new Stack<Foo>(); 
    foos.Add(foo()); 
start_subroutine: 
    A() 
    for (;;) 
    { 
    B(); 
    if (C()) 
    { 
     //instead of returning from a recursive call 
     if (foos.Count > 1) 
     { 
     foo = foos.Pop(); 
     goto end_subroutine; 
     } 
     return; 
    } 
    if (D()) 
    { 
     //instead of invoking Run as a subroutine, bring its functionality inline 
     //Run(); 
     X(); 
     if (Y()) 
     { 
     //instead of calling self recursively 
     //Parse(); 
     //push onto a local stack variable and jump 
     foos.Add(foo); 
     goto start_subroutine; 
     } 
end_subroutine: 
     Z(); 
    } 
    E(); 
    } 
} 

私はこれを行うといいんだけど、私はgoto文を使用せずにそれを行うにはどのように表示されていません。 gotoが必要な場合の1つであると誰かが書いていることをいつも覚えていることは覚えていません。

+15

プロファイラの脆弱性に合わせてコードを書き直す考えは、最近私が遭遇したのが一番奇妙です。 –

+2

私はCの人々が行う「奇妙なこと」の増加するリストにそのことを言います

+1

@Dirk - 私はそれがこの道を導いたのはフリーソフトウェアの追求だと思います。 – ChrisF

答えて

2

あなたは正しい道にいると思います!私はこの場合にgotoを使用して実際の問題は表示されません。コード内で何が起こっているのかは本当にはっきりしています。実際に、直接ジャンプを避けようとする唯一の理由は、他人のコードを読むときに混乱を招く可能性があるからです。

これをきちんと構造化しておき、ほとんどの実装コードを他の関数で使用すると、これは完全に合理的です。特に、プロファイリングのために非再帰的なコードを使用しているだけなので):

幸いですが、あなたは手続きを完了します!

+0

自信を持って投票してくださってありがとうございます。はい、もし非再帰的にそれを行うきちんとした方法がないなら、私は '#if'を使ってコードの両方のバージョンを保持しています(プロファイリングのためだけ非再帰バージョンを使用します)。 – ChrisW

+3

それは完全にプロファイリングのpuroseを倒すことはありませんか? –

+0

いいえ:これらのトップレベルメソッドをプロファイルするのではなく、代わりにこれらのメソッドのサブルーチンと呼ばれる10個のKLOCをプロファイリングしています。OPの擬似コードの例のA、B、Cなどのメソッド)。トップレベルコードの両方のバージョン(再帰的および非再帰的)は、サブルーチンを同じ順序で同じ順序で呼び出します。 – ChrisW

2

私は本当にこれをテストすることはできませんが、それは本当にすべてだ場合は、私はよく分からない

Z(); 
E(); 
continue; 

A(); 
continue; 

goto end_subroutinegoto start_subroutineを置き換えることができますように私には思われますはるかに優れています:)

+0

あなたの提案をありがとう。 – ChrisW

関連する問題