Когда и как использовать стиль передачи продолжения - PullRequest
13 голосов
/ 21 августа 2009

Я читал о технике программирования стиля передачи продолжения (реализация C # 3.0).

Почему / когда было бы полезно использовать эту технику?

Как я могу реализовать это, чтобы получить эти действительно длинные цепочки? Это то же самое, что карри (что дает лучшие результаты поиска в Google)?

Спасибо

Ответы [ 3 ]

12 голосов
/ 21 августа 2009

отличная запись на CPS в контексте C # была сделана Уэсом Дайером Я не думаю, что мог бы добавить что-либо значимое к этому. Если какие-то конкретные вещи там неясны, спросите о них.

5 голосов
/ 21 августа 2009

Чтобы ответить на ваш последний вопрос, стиль передачи продолжения - это не то же самое, что карри. Вы каррируете, когда создаете функцию из другой функции, указывая один или несколько ее параметров, таким образом получая функцию с меньшим количеством параметров. Карринг в функциональном языке программирования, таком как F # и C # в некоторой степени, позволяет вам рассматривать все функции как функции одной переменной. Если указанная функция имеет более одного параметра, то ее можно рассматривать как имеющую параметр и возвращающую другую функцию с оставшимися параметрами. Это пример карри в c #:

public static class FuncExtensions
{
        public static Func<A, Func<R>> Curry<A, R>(this Func<A, R> f)
        {
            return a => () => f(a);
        }
}

Func<int, int> f = x => x + 1;

Func<int> curried = f.Curry()(1);

Там, где функция curry всегда будет возвращаться 2. Конечно, есть и более полезные варианты использования.

Что касается стиля передачи продолжения, в дополнение к блогу Уэса Дайера, на который есть ссылка, рассмотрите асинхронные рабочие процессы F #, которые являются экземплярами продолжений или монадой продолжения. Вы можете попытаться использовать термин «монада продолжения», чтобы найти дополнительные статьи.

0 голосов
/ 06 января 2019

Я нашел краткое и хорошее объяснение CPS в книге Риккардо Террелла «Параллельность в .NET, Современные шаблоны параллельного и параллельного программирования» (код на C #):

Иногда оптимизированные рекурсивные функции хвостового вызова не подходят решение или может быть трудным для реализации. В этом случае один из возможных альтернативный подход - CPS, метод передачи результата функция в продолжение. CPS используется для оптимизации рекурсивного функции, потому что это избегает выделения стека. Кроме того, CPS используется в Microsoft TPL, в async / await в C # и в асинхронном рабочем процессе в F #. CPS играет важную роль в параллельном программировании. Это следующее Пример кода показывает, как шаблон CPS используется в функции GetMaxCPS:

static void GetMaxCPS(int x, int y, Action<int> action) => action(x > y ? x : y);

GetMaxCPS (5, 7, n => Console.WriteLine(n));

Аргумент для передачи продолжения определяется как делегат Действие, которое удобно использовать для прохождения лямбды выражение. Интересно то, что функция с этим дизайном никогда не возвращает результат напрямую; вместо этого он предоставляет результат процедура продолжения. CPS также может быть использован для реализации рекурсивные функции с использованием хвостовых вызовов.

Вот также простое и краткое объяснение из Википедии. В объяснении также упоминаются преимущества CPS:

https://en.wikipedia.org/wiki/Continuation-passing_style

Функция, написанная в стиле продолжения, требует дополнительного Аргумент: явное «продолжение», то есть функция одного аргумента. Когда функция CPS вычислила свое значение результата, она «возвращает» его вызывая функцию продолжения с этим значением в качестве аргумента. Это означает, что при вызове функции CPS вызывающая функция требуется предоставить процедуру, которая будет вызываться с подпрограммой возвращаемое значение Выражение кода в этой форме делает ряд вещей явные, которые неявно в прямом стиле. К ним относятся: процедура возвраты, которые становятся очевидными как призывы к продолжению; промежуточные значения, которым являются все заданные имена; порядок аргументации оценка, которая сделана явной; и хвостовые вызовы, которые просто называют процедура с тем же продолжением, без изменений, которая была передана звонящий.

Программирование с продолжениями также может быть полезно, когда вызывающая сторона не хочет ждать, пока вызываемая программа завершит работу. Например, в программировании пользовательского интерфейса подпрограмма может установить диалоговое окно поля и передать их вместе с функцией продолжения в пользовательский интерфейс фреймворк. Этот вызов возвращается сразу, позволяя код приложения продолжить, пока пользователь взаимодействует с диалоговым окном. Однажды пользователь нажимает кнопку «ОК», фреймворк вызывает продолжение функция с обновленными полями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...