3

メソッド本体内でラムダ式として定義され、変数に割り当てられた階乗関数を考えてみましょう。

Func<int, int> factfail = n =>
{
    if (n == 0)
        return 1;
    else
        return n * factfail(n-1);
};

factfailまだローカル変数にバインドされていないため、これは失敗します。

関数自体を抽象化して、一種の修正点を追加する方法はありますか?!

Func<Func<int, int>, int, int> fact_ = (fact, n) => 
{  
    if (n == 0) 
        return 1;
    else 
        return n * fact(n-1); 
};

fact_(??);

長い話: 外部の状態を変更するという副作用を持つ再帰関数を作成する必要があります。したがって、そのメソッドをその外側の状態をキャプチャするラムダ式として記述しようとしています。

私はまだそれを書く方法をさまざまなスタイルで試しています.そして-すべての再帰呼び出しで同じである必要がある1つの辞書に加えて-私はできるだけ純粋に機能的で怠惰になりたいです。

相互データを減らすのに役立つので、LINQで遊んでいました。また、コードのどの部分を機能的なスタイルで表現できるかを理解するのにも役立ちます。

簡単に言うと、LINQ ステートメントの前にいくつかのヘルパー関数を定義できると便利です。ラムダ式を変数にバインドすることでそれを行いました。

また、ラムダ式を使用すると、メソッドへの参照を明示的に渡す必要なく辞書をキャプチャすることもできます。これは非常に優れています。

私が正しい軌道に乗っているかどうかはわかりませんが...

4

1 に答える 1

3

再帰ラムダ式の詳細については、Mads Torgersen によるこのブログ投稿を参照してください。彼は、通常の不動点コンビネータを定義する方法を示しています。彼は階乗関数を例として使用しているので、そこに正確なサンプルを見つけることができます:-)。

ただし、実際には、ローカルFunc<..>変数を定義してから変更するだけです。デリゲートに名前を付けたい場合は、問題なく機能します (少し汚いですが、単純です)。

Func<int, int> fact = null;
fact = (n) => (n == 0) ? 1 : n * fact(n-1);

クロージャーがfact変数への参照をキャプチャするため、これは機能します。そのため、実際に呼び出すと (再帰呼び出し中に)、値はnullもはやではなく、デリゲートを参照します。

于 2011-04-05T22:02:03.947 に答える