什么是通话/抄送? [英] What is call/cc?

查看:103
本文介绍了什么是通话/抄送?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试了几次以理解 continuations

I've tried several times to grasp the concept of continuations and call/cc. Every single attempt was a failure. Can somebody please explain me these concepts, ideally with more realistic examples than these on Wikipedia or in other SO posts.

我具有Web编程和OOP的背景.我也了解6502的组装,并与Erlang有轻微的约定.但是,仍然无法绕过call/cc.

I have background in web programming and OOP. I also understand 6502 assembly and had a minor randez-vous with Erlang. However still, I can't wrap my head around call/cc.

推荐答案

看,我发现了这个继续传递对此主题的最佳描述.

Look, i've found this Continuation Passing Style best description on this topic.

以下是该文章的详细信息副本:

Here's stripped of details copy of that article:

作者:Marijn Haverbeke 日期:2007年7月24日

Author: Marijn Haverbeke Date: July 24th 2007

Scheme的当前连续调用功能可以捕获计算,调用堆栈的状态,并在以后恢复该状态.除了这种原始语言外,还可以实现各种形式的异常处理和类似C的longjmp技巧.

Scheme's call-with-current-continuation function makes it possible to capture a computation, a state of the call stack as it were, and resume that same state at a later time. On top of such a primitive, various form of exception handling and C-like longjmp tricks can be implemented.

function traverseDocument(node, func) {
  func(node);
  var children = node.childNodes;
  for (var i = 0; i < children.length; i++)
    traverseDocument(children[i], func);
}   

function capitaliseText(node) {
  if (node.nodeType == 3) // A text node
    node.nodeValue = node.nodeValue.toUpperCase();
}

traverseDocument(document.body, capitaliseText);

这可以如下转换:我们向每个函数添加一个额外的参数,该参数将用于传递函数的延续.此延续是一个函数值,表示在函数返回"之后必须发生的动作. (调用)堆栈在连续传递样式中变得过时了-当一个函数调用另一个函数时,这是它要做的最后一件事.无需等待被调用的函数返回,而是将其后要执行的所有工作放入延续中,并传递给该函数.

This can be transformed as follows: We add an extra argument to every function, which will be used to pass the function's continuation. This continuation is a function value representing the actions that must happen after the function 'returns'. The (call) stack becomes obsolete in continuation-passing style ― when a function calls another function, that is the last thing it does. Instead of waiting for the called function to return, it puts any work it wants to do afterwards into a continuation, which it passes to the function.

function traverseDocument(node, func, c) {
  var children = node.childNodes;
  function handleChildren(i, c) {
    if (i < children.length)
      traverseDocument(children[i], func,
                       function(){handleChildren(i + 1, c);});
    else
      c();
  }
  return func(node, function(){handleChildren(0, c);});
}

function capitaliseText(node, c) {
  if (node.nodeType == 3)
    node.nodeValue = node.nodeValue.toUpperCase();
  c();
}

traverseDocument(document.body, capitaliseText, function(){});

想象一下,我们有一份大胆的文件可以大写.一口气遍历它需要五秒钟,而将浏览器冻结五秒钟是相当糟糕的样式.考虑一下对capitaliseText的简单修改(不要关注丑陋的全局变量):

Imagine we have a huuuuge document to capitalise. Just traversing it in one go takes five seconds, and freezing the browser for five seconds is rather bad style. Consider this simple modification of capitaliseText (don't pay attention to the ugly global):

var nodeCounter = 0;
function capitaliseText(node, c) {
  if (node.nodeType == 3)
    node.nodeValue = node.nodeValue.toUpperCase();

  nodeCounter++;
  if (nodeCounter % 20 == 0)
    setTimeout(c, 100);
  else
    c();
}

现在,每20个节点,计算中断100毫秒,使浏览器界面有时间响应用户输入.一种非常原始的线程形式-您甚至可以像这样同时运行多个计算.

Now, every twenty nodes, the computation is interrupted for a hundred milliseconds to give the browser interface a moment to respond to user input. A very primitive form of threading ― you can even run multiple computations at the same time like this.

此方法的一个更常用的应用程序与XMLHttpRequests或用于模拟它们的各种IFRAME和SCRIPT标记黑客有关.这些总是需要使用某种回调机制来处理服务器发回的数据.在简单的情况下,可以使用一个简单的函数,或者可以使用一些全局变量来存储必须在数据返回后恢复的计算状态.在复杂的情况下,例如,当数据正在使用的函数必须向其调用者返回一些值时,延续会大大简化事情.您只需将继续注册为回调,然后在请求完成时恢复计算.

A more commonly useful application of this is related to XMLHttpRequests, or the various IFRAME and SCRIPT tag hacks used to simulate them. These always require one to work with some kind of call-back mechanism to handle the data that the server sends back. In simple cases, a trivial function will do, or a few globals can be used to store the state of the computation that must be resumed after the data comes back. With complex cases, for example when the data is being used by a function that must return some value to its caller, continuations simplify things considerably. You just register the continuation as the call-back, and your computation is resumed when the request finishes.

这篇关于什么是通话/抄送?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆