答えて

5

はい、yield returnは継続形式です。 Linqは、多くの便利なケースでは、遅延ジェネレータをプラグインできる関数演算子を提供しています。したがって、C#3では実際にyield returnを使用する必要はありません(Linqスタイルの拡張をライブラリーのプラグギャップ、例えばZip、Unfold)。

この例では、ブルートフォースで整数を因数分解する。基本的にC#で同じ例が内蔵されたLINQの演算子を使って行うことができます。

var factors = Enumerable.Range(2, 100) 
     .Join(Enumerable.Range(2, 100), 
       n => 1, n => 1, (i, j) => new { i, j }) 
     .First(v => v.i*v.j == 481); 

Console.WriteLine("Factors are " + factors.i + ", " + factors.j); 

ここでは出発点が内蔵されているのLINQにEnumerable.Rangeへの私の二つの呼び出し、ですが、あなたのように自分自身を実現することができます。

IEnumerable<int> Range(int start, int stop) 
{ 
    for (int n = start; n < stop; n++) 
     yield return n; 
} 

2つの奇数のパラメータ、Joinn => 1n => 1のパラメータがあります。私はJoinのキー値として1を選択して項目をマッチングするので、すべての組み合わせが一致するため、範囲の数値のすべての組み合わせをテストします。

そして私はタプルの種類(匿名型)に値のペアをオン:最後に、私は私のテストが満足された最初のそのようなタプルを選択

(i, j) => new { i, j }) 

.First(v => v.i*v.j == 481); 

更新

コール内のコードFirst単に短いテスト式である必要はありません。これは、テストが失敗した場合、「再起動」する必要が不可欠コードの全体の多くすることができます:

.First(v => 
     { 
      Console.WriteLine("Aren't lambdas powerful things?"); 

      return v.i*v.j == 481; 
     ); 

ので、潜在的に異なる値を使用して再起動する必要があり、プログラムの一部は、ラムダになります。ラムダが異なる値で自分自身を再起動したいときは常に、falseを返します。ambを引数なしで呼び出すのと同じです。

+1

ニースコード - ただしambとはかなり異なる効果があります。 Ambは、次の計算だけでなく、コード全体が失敗しないようにその値を選択します。 – Dario

+1

「再起動」は特定のコンテキストに限定する必要がありますが、実装されています。具体的には、amb変数が導入される前に行われたすべての作業を含めて、プログラム全体を再起動するのは愚かでしょう!私のバージョンでは、これはamb変数をシーケンスにチャネリングすることで明確になり、再始動可能なコンテキストはFirstに渡されたラムダです - これを明確にする可能性がある上記の更新を参照してください。ラムダのコードは、任意に複雑にすることができます。 –

+0

合意した素敵なコードですが、これは決定的な総当たりの実装です。これは、非同期的な並行実装ではなく、AMB演算子を実装する際の重要な属性の2つと考えられます。副作用として、この投稿以来、Rxはリリースされており、Ambオペレータを持っています。 –

5

これはあなたの質問に対する答えではありませんが、あなたが望むものを得ることができます。

ambは、非決定論的コンピューティングに使用されます。ご存知のように、Prologは統一の概念を使って値を変数に結びつける非決定論的言語です(基本的にはambがやっていることです)。

この機能の実装は、YieldPrologというC#で実装されています。あなたが推測したように、産出オペレータはこのための重要な必要条件です。

http://yieldprolog.sourceforge.net/

関連する問題