amb-operator による非決定的な選択
-
22-08-2019 - |
質問
実装は可能ですか マッカーシーズ amb
-オペレーター C# で非決定的な選択をするには?
どうやら .NET には継続サポートが欠けているようですが、 yield return
役に立つかもしれない。これは F# などの他の静的 .NET 言語でも可能でしょうか?
解決
はい、 yield return
継続の形をとります。ただし、多くの便利な場合に、Linq は遅延シーケンス ジェネレーターを接続できる関数演算子を提供するため、実際には C# 3 では使用する必要はありません。 yield return
(ライブラリ内のギャップを埋めるために独自の Linq スタイルの拡張機能を追加する場合を除く)。圧縮、展開)。
この例では、総当たりで整数を因数分解します。基本的に同じ例を 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);
ここでの出発点は、私の 2 つの呼び出しです。 Enumerable.Range
, これは Linq に組み込まれていますが、次のように自分で実装することもできます。
IEnumerable<int> Range(int start, int stop)
{
for (int n = start; n < stop; n++)
yield return n;
}
奇妙なパラメータが 2 つあります。 n => 1
, n => 1
パラメータを Join
. 。のキー値として 1 を選択します。 Join
項目を一致させるときに使用するため、すべての組み合わせが一致するため、範囲内の数値のすべての組み合わせをテストできます。
次に、次のように値のペアを一種のタプル (匿名型) に変換します。
(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#で、この機能の実装は、あります。あなたが推測として、歩留まりのオペレータは、このための重要な必要条件である。