McCarthy's amb
-operatorをC#で非確定的な選択に実装することは可能ですか?amb-operatorで非決定的な選択
明らかに.NETには継続サポートがありませんが、yield return
が役に立ちます。これはF#のような他の静的.NET言語でも可能でしょうか?
McCarthy's amb
-operatorをC#で非確定的な選択に実装することは可能ですか?amb-operatorで非決定的な選択
明らかに.NETには継続サポートがありませんが、yield return
が役に立ちます。これはF#のような他の静的.NET言語でも可能でしょうか?
はい、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つの奇数のパラメータ、Join
へn => 1
、n => 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
を引数なしで呼び出すのと同じです。
これはあなたの質問に対する答えではありませんが、あなたが望むものを得ることができます。
ambは、非決定論的コンピューティングに使用されます。ご存知のように、Prologは統一の概念を使って値を変数に結びつける非決定論的言語です(基本的にはambがやっていることです)。
この機能の実装は、YieldPrologというC#で実装されています。あなたが推測したように、産出オペレータはこのための重要な必要条件です。
ニースコード - ただしambとはかなり異なる効果があります。 Ambは、次の計算だけでなく、コード全体が失敗しないようにその値を選択します。 – Dario
「再起動」は特定のコンテキストに限定する必要がありますが、実装されています。具体的には、amb変数が導入される前に行われたすべての作業を含めて、プログラム全体を再起動するのは愚かでしょう!私のバージョンでは、これはamb変数をシーケンスにチャネリングすることで明確になり、再始動可能なコンテキストはFirstに渡されたラムダです - これを明確にする可能性がある上記の更新を参照してください。ラムダのコードは、任意に複雑にすることができます。 –
合意した素敵なコードですが、これは決定的な総当たりの実装です。これは、非同期的な並行実装ではなく、AMB演算子を実装する際の重要な属性の2つと考えられます。副作用として、この投稿以来、Rxはリリースされており、Ambオペレータを持っています。 –