What is call/cc?

前端 未结 11 1093
无人共我
无人共我 2020-12-07 12:55

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

11条回答
  •  自闭症患者
    2020-12-07 12:59

    You're probably familiar with the idea of "transfer of control", which - in languages like C - manifests itself in statements such as break, continue, return and goto, or - in languages that support exceptions - the try and catch statements.

    You can imagine that break and continue could be implemented using goto (i.e. for every piece of code that uses break or continue, you could easily write equivalent code that uses goto with appropriately placed labels).

    So for now let's focus on goto, which - as you should know from your experience with assembly - is the most basic control transfer operation (you can imagine that it would be hard to transform return to use goto - but we'll get on to this).

    So let's suppose that you have a program (say, in C) that looks like this:

    instruction1;
    instruction2;
    ...
    instructionN;
    

    where instructionK could either be an assignment or a function call or the statement if (condition) goto some_label.

    You could prepend each line with a unique label for goto:

    line1: instruction1;
    line2: instruction2;
    ...
    lineN: instructionN;
    

    In languages that support first-class continuations, there is a special function call/cc, which works like this: suppose that instructionK has the form

    ...
    lineK: call/cc(function(continuation) { ... })
    lineK+1: instructionK+1;
    ...
    

    I have used JavaScript's notation for anonymous functions here, because C does not support anonymous functions. You can see that the function has one argument, which I have called continuation.

    The body of the function is executed immediately when call/cc is invoked, and the value of the continuation argument will be the address of lineK+1 (roughly speaking). Or, in other words, the current continuation in lineK is the lineK+1 - this is how you could think about it.

    However, the typical interface is that it's not just address: the continuation argument is a procedure which, when invoked, performs a jump to the lineK+1. This is how call/cc allows to implement a return statement.

    So you could think of call/cc as a kind of a goto on steroids. The thing is, that you can not only call the continuation argument, but you can also store it in variables or other data structures.

    The most interesting use of call/cc that I have seen is the implementation of the Amb evaluator from Dorai Sitaram's book Teach Yourself Scheme in Fixnum Days (you can compare it with the version from Structure and Interpretation of Computer Programs which doesn't use call/cc).

    I have once also implemented my own mechanism for resource management using continuations, as described here.

    But other than that, first-class continuations were subject to criticism, and I wouldn't recommend using them in production code (they are very similar to the setjmp/longjmp mechanism available in C, which I would also discourage. But if you'd like to see some usage example, here's how you could use it to implement multitasking in 100 lines od code).

提交回复
热议问题