回答

5

是,yield return确实延续的一种形式。尽管对于很多有用的案例,Linq提供了允许你将懒惰序列生成器连接在一起的函数操作符,所以事实上在C#3中,不需要使用yield return(除非添加更多的Linq样式扩展到自己的插入库中的间隙,例如Zip,Unfold)。

在这个例子中,我们用蛮力分解了一个整数。

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,但你可以实现自己作为:

基本上在C#中相同的例子可以用内置的LINQ运算符来完成
IEnumerable<int> Range(int start, int stop) 
{ 
    for (int n = start; n < stop; n++) 
     yield return n; 
} 

有两个奇数参数,所述n => 1n => 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; 
     ); 

所以这可能需要使用不同的值重新启动该计划的一部分进入该拉姆达。每当lambda想要用不同的值重新启动时,它只会返回false - 相当于调用amb而没有参数。

+1

不错的代码 - 但它有一个不同于amb的效果。 Amb选择它的值,使得整个代码不会失败,而不仅仅是下面的计算。 – Dario 2009-07-06 17:14:54

5

这不是你的问题的答案,但它可能会得到你想要的。

amb用于非确定性计算。正如你可能知道的,Prolog是一种非确定性的语言,它使用统一的概念将值绑定到变量(基本上什么是最终做的)。

在C#中有一个名为YieldProlog的实现。正如你猜测的那样,收益运营商对此是一个重要的必要条件。

http://yieldprolog.sourceforge.net/