Выбор Non-determinstic с amb-оператором

PHP (PHPUnit)

Использует расширение PHPUnit_Selenium версии 1.2.7:

class MyTestClass extends PHPUnit_Extensions_Selenium2TestCase {
    ...
    public function screenshot($filepath) {
        $filedata = $this->currentScreenshot();
        file_put_contents($filepath, $filedata);
    }

    public function testSomething() {          
        $this->screenshot('/path/to/screenshot.png');
    }
    ...
}
5
задан Dario 3 July 2009 в 17:11
поделиться

2 ответа

Yes, yield return does a form of continuation. Although for many useful cases, Linq provides functional operators that allow you to plug together a lazy sequence generator, so in fact in C# 3 it isn't necessary to use yield return so much (except when adding more Linq-style extensions of your own to plug gaps in the library, e.g. Zip, Unfold).

In the example we factorise an integer by brute force. Essentially the same example in C# can be done with the built-in Linq operators:

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);

Here the starting points are my two calls to Enumerable.Range, which is built-in to Linq but you could implement yourself as:

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

There are two odd parameters, the n => 1, n => 1 parameters to Join. I'm picking 1 as the key value for Join to use when matching up items, hence all combinations will match and so I get to test every combination of numbers from the ranges.

Then I turn the pair of values into a kind of tuple (an anonymous type) with:

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

Finally, I pick the first such tuple for which my test is satisfied:

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

Update

The code inside the call to First need not be merely a short test expression. It can be a whole lot of imperative code which needs to be "restarted" if the test fails:

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

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

So the part of the program that potentially needs to be restarted with different values goes in that lambda. Whenever that lambda wants to restart itself with different values, it just returns false - the equivalent of calling amb with no arguments.

5
ответ дан 13 December 2019 в 22:14
поделиться

Это не ответ на ваш вопрос, но он может дать вам то, что вы хотите.

amb используется для недетерминированных вычислений. Как вы, возможно, знаете, Prolog - это недетерминированный язык, использующий понятие унификации для привязки значений к переменным (в основном то, что в итоге делает amb).

Существует реализация этой функциональности в C #, которая называется YieldProlog. Как вы уже догадались, для этого необходим оператор yield.

http://yieldprolog.sourceforge.net/

5
ответ дан 13 December 2019 в 22:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: