C# amb算子的非确定性选择
是否可以在C#中实现非确定性选择C# amb算子的非确定性选择,c#,.net,functional-programming,continuations,non-deterministic,C#,.net,Functional Programming,Continuations,Non Deterministic,是否可以在C#中实现非确定性选择 显然.NET缺乏延续性支持,但是收益率可能会很有用。在其他静态.NET语言中,如F#?是的,yield-return是一种延续形式。尽管在许多有用的情况下,Linq提供了函数运算符,允许您插入一个惰性序列生成器,因此实际上在C#3中,不需要使用太多的yield return(除非添加更多自己的Linq样式扩展来插入库中的间隙,例如Zip、Unfold) 在这个例子中,我们用蛮力分解一个整数。本质上,C#中的相同示例可以通过内置Linq操作符完成: var fac
显然.NET缺乏延续性支持,但是
收益率可能会很有用。在其他静态.NET语言中,如F#?是的,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);
这里的起点是我对Enumerable.Range
的两个调用,它内置于Linq中,但您可以将自己实现为:
IEnumerable<int> Range(int start, int stop)
{
for (int n = start; n < stop; n++)
yield return n;
}
最后,我选择了第一个满足测试要求的元组:
.First(v => v.i*v.j == 481);
更新
对First
的调用中的代码不必仅仅是一个简短的测试表达式。如果测试失败,可能需要“重新启动”大量命令式代码:
.First(v =>
{
Console.WriteLine("Aren't lambdas powerful things?");
return v.i*v.j == 481;
);
因此,程序中可能需要使用不同值重新启动的部分位于lambda中。每当lambda想要用不同的值重新启动它自己时,它只返回false——相当于调用没有参数的amb
。这不是对您的问题的回答,但它可能会得到您想要的
amb用于非确定性计算。您可能知道,Prolog是一种非确定性语言,使用统一的概念将值绑定到变量(基本上是amb最终所做的)
这个功能在C#中有一个实现,称为YieldProlog。正如您所猜测的,收益率操作符是实现这一点的重要必要条件
代码不错-但它的效果与amb截然不同。Amb选择它的值,这样整个代码就不会失败,而不仅仅是下面的计算;具体来说,重新启动整个程序(包括引入amb变量之前所做的所有工作)是愚蠢的!在我的版本中,这是通过将amb变量导入一个序列来明确的,然后可重启上下文是传递给First的lambda-请参阅上面的更新,这可能会更清楚。lambda中的代码可能任意复杂。同意,代码不错,但这是一个确定性的暴力实现。这不是一个并发的非确定性实现,我认为这是实现AMB操作符的两个关键属性。作为旁注,由于这篇文章,Rx被发布了,并且确实有一个Amb操作员。
.First(v =>
{
Console.WriteLine("Aren't lambdas powerful things?");
return v.i*v.j == 481;
);