What is the difference between the continuations of the Scheme and those of other languages?

8

I've heard that the Scheme has "first-class continuations", while other Lisps (and other languages) do not. I researched this, but the material I found was not specific.

What I understand is that continuations are like the callback functions in Node.js, but with a different purpose. For example, without continuation:

(define (ao-quadrado x)
  (* x x))

And with continuation:

(define (ao-quadrado x cont)
  (cont (* x x)))

Is there any other difference? Did I miss something on the way?

    
asked by anonymous 07.02.2014 / 17:30

2 answers

3

The callback functions of nodejs are not a particular case of continuations. "Continuation" is a more generic term than this.

Translating from wikipedia :

  

A continuation is an abstract representation of the execution flow state of a program. A continuation reifies implicit flow control in an explicit function

For example, suppose I am making the following account:

(define (conta)
  (* (+ 1 2) 4))

There is an implicit flow control command when I perform these operations. I'd like to explain it by converting the program to single assignment form:

a <- 1 + 2
b <- a * 4

Continuations are one way of representing this implicit order of execution. Given a point in the code, the continuation of that point is a function that represents what will happen in the future. For example, the continuation of the sum operation point on the third line is a (lambda (a) (a * 4))

One thing we can do with continuations is to write our program so that the continuations appear explicitly. This is called Continuation Passing Style and that's what people do on Nodejs. In our example, this would be to use operations like + -cps and * -cps instead of + and * which return values:

(define (conta-cps cont)
  (+-cps 1 2 (lambda (a)
    (*-cps a 4 cont)))

Programming like this has some benefits. For example, with continuations you can "pause" code execution. Just grab the continuation and save it into some data structure and call it back later. Proceedings also allow you to implement some control mechanisms yourself, such as "return", "try-catch", and iterators.

The problem is that it is a bag to convert all your functions to CPS at hand. This is where first-class continuations come in, using call-with-current-continuation (call / cc) you can write your code without continuations but you have access to the continuations as if you had written the code in CPS. >

I will not give examples of call / cc because I think the code gets very complicated. In practice you can use other less powerful tools that give you similar benefits (being able to pause and restart the program, etc.). For example, in Scheme there are delimited continuations, in Python you have generators and in Lua you have corotinas.

    
07.02.2014 / 20:57
5

The continuations in Scheme are like increased closures that capture the return stack, the environment, and the current execution point. In other languages, such as JavaScript, continuations are "mere" functions or closures that capture the environment around.

In this way, it is possible, for example, to pick up a mapping function, which typically calls a function for each element, and make an iterator, which is called to return the following element:

(define (my-hash-iterator a-hash)
  (let ((return-values #f)
        (read-value #f))
    (lambda ()
      (let/cc iteration
        (set! return-values iteration)
        (if read-value
            (read-value)
            (begin
              (hash-table-for-each a-hash
                                   (lambda (key value)
                                     (let/cc cont
                                       (set! read-value cont)
                                       (return-values #t key value))))
              (set! read-value #f)    ; iterador volta ao início se chamado novamente
              (return-values #f #f #f)))))))

The idea is to enter the function given to hash-table-for-each and take a continuation inside, (set! read-value cont) , which when invoked, will return it to hash-table-for-each . The continuation from outside is to return each of the values in turn.

    
15.02.2014 / 00:46