Вопрос

Возможно ли это реализовать У Маккарти amb-оператор для недетерминированного выбора в C #?

Очевидно.СЕТИ не хватает поддержки продолжения, но yield return могло бы быть полезно.Было бы ли это возможно в других статических .СЕТЕВЫЕ языки, такие как F #?

Это было полезно?

Решение

ДА, 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);

Здесь отправными точками являются мои два призыва к Enumerable.Range, который встроен в Linq , но вы могли бы реализовать себя как:

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

Есть два нечетных параметра, 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).

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

http://yieldprolog.sourceforge.net/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top