我一直在阅读有关继续传递样式编程技术(C#3.0实现)的内容。
为何/何时使用此技术会有用?
如何实现这一点以获得真正的长链?这与currying相同(这会在google中产生更好的搜索结果)吗?
由于
答案 0 :(得分:12)
Wes Dyer在C#环境中对CPS进行了excellent write-up。我认为我不可能添加任何有意义的东西。如果某些具体事情不明确,请继续询问。
答案 1 :(得分:5)
要回答你的上一个问题,继续传递风格不是一个currying。当你从另一个函数创建一个函数时,你可以通过指定一个或多个参数来进行curry,从而获得一个参数更少的函数。在函数式编程语言(例如F#和C#)中进行一定程度的使用,可以将所有函数视为一个变量的函数。如果所述函数具有多个参数,则可以将其视为具有on参数并返回具有其余参数的另一函数。这是c#中的currying示例:
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);
咖喱功能将永远返回2.当然,这有更多的启发性用途。
关于继续传递样式,除了链接到的Wes Dyer博客之外,还要查看F#异步工作流,它们是continuation的实例,或者是continuation monad。您可以尝试使用术语continuation monad来查找其他一些文章。
答案 2 :(得分:0)
我在Riccardo Terrell撰写的“ .NET中的并发,并发和并行编程的现代模式”一书中找到了关于CPS的简短且很好的解释(代码在C#中):
有时候,优化的尾调用递归函数不正确 解决方案或可能难以实施。在这种情况下,一种可能 另一种方法是CPS,一种传递结果的技术 功能延续。 CPS用于优化递归 功能,因为它避免了堆栈分配。此外,CPS用于 Microsoft TPL,在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));
连续传递的参数定义为委托 动作,可以方便地用于传递lambda 表达。有趣的部分是该设计的功能 从不直接返回结果;相反,它将结果提供给 继续过程。 CPS也可以用于实施 使用尾部调用的递归函数。
这里也是Wikipedia的简单简短说明。解释还提到了CPS的好处:
https://en.wikipedia.org/wiki/Continuation-passing_style
以连续传递样式编写的函数需要额外花费 参数:明确的“继续”,即一个参数的函数。 当CPS函数计算出其结果值时,它将“返回”它 通过使用该值作为参数调用延续函数。 这意味着在调用CPS函数时,调用函数为 需要提供要与子例程的程序一起调用的过程 “返回”值。以这种形式表达代码可以做很多事情 显式的,以直接样式隐式表示。这些包括:过程 回报,作为继续的呼唤变得显而易见; 中间值,都是给定的名称;论证顺序 明确的评估;和尾叫,简单地叫 具有相同连续性且未修改的过程,该过程已传递给 呼叫者,召集者。
当 呼叫者不想等到被呼叫者完成。例如, 在用户界面(UI)编程中,例程可以设置对话框 字段,并将其以及延续功能传递给用户界面 框架。该调用立即返回,允许应用程序代码 在用户与对话框交互时继续操作。一旦 用户按下“确定”按钮,框架调用继续 功能与更新的字段。