1

The Scheme Programming Languages says

Thus, at any point during the evaluation of any expression, there is a continuation ready to complete, or at least continue, the computation from that point. Let's assume that x has the value (a b c). We can isolate six continuations during the evaluation of (if (null? x) (quote ()) (cdr x)) -- the continuations waiting for

  1. the value of (if (null? x) (quote ()) (cdr x)),
  2. the value of (null? x),
  3. the value of null?,
  4. the value of x,
  5. the value of cdr, and
  6. the value of x (again).

The continuation of (cdr x) is not listed because it is the same as the one waiting for (if (null? x) (quote ()) (cdr x)).

I was wondering how to write (if (null? x) (quote ()) (cdr x)) in CPS?

Can only procedure calls be rewritten in CPS?

Will Ness
  • 70,110
  • 9
  • 98
  • 181

2 Answers2

1

The challenge with (if (null? x) (quote ()) (cdr x)) is that it really doesn't do anything. eg. if I put that in an R6RS-program and run it nothing happens. Thus I suggest we write it:

(display (if (null? x) (quote ()) (cdr x)))

And assume this is the whole program except that x is defined. Now if needs to know the value of (null? x) to determine if it is the consequent or the alternative. eg.

(null?& x
        continuation)

The continuation needs to determine if it's true or not and do one of two continuations:

(null?& x
        (lambda (xn)
          (if& xn
               continuation-consequent
               continuation-alternative)))

If xn is true the continuation should display '(), but if it is not then it shoudl display the cdr of x:

(null?& x
        (lambda (xn) ; 201
          (if& xn
               (lambda () ; 202 
                 (display& '() halt)
               (lambda () ; 203 
                 (cdr& x (lambda (cdrx) ; 204
                           (display& cdrx halt)))))))

halt stops the program. Now lets imagine we translate this to Algol eg. JS. I'll switch the order so that continuation always is the first argument. All procedures just gets an numeric id so the implementation language doesn't need to have procedures at all.

const undef = "BaNaNa";
const x = [1, 2, 3]; // change this
const stack = [200];
main:
  while (true) {
    const cont = stack.pop();
    const cont2 = cont < 200 ? stack.pop() : undef;
    switch (cont) {
      case 1: // null?&
        stack.push(stack.pop().length === 0, cont2);
        break;
      case 2: // display&
        console.log(stack.pop());
        stack.push(undef, cont2);
        break;
      case 3: // cdr&
        stack.push(stack.pop().splice(1), cont2);
        break;
      case 4: // if&
        const cont3 = stack.pop();
        if (stack.pop()) {
          stack.push(cont2);
        } else {
          stack.push(cont3);
        }
        break;
        // continuations
      case 200:
        stack.push(x, 201, 1);
        break;
      case 201:
        stack.push(203, 202, 4);
        break;
      case 202:
        stack.push([], 1337, 2);
        break;
      case 203:
        stack.push(x, 204, 3);
        break;
      case 204:
        stack.push(1337, 2);
        break;
        // halt     
      case 1337:
        break main;
    }
  }

Now we did miss out on user specified procedures and closure conventions, both which would have made this example slightly more complex. There is some missing type checking a proper Scheme would have done and I use arrays instead of real pairs.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
0

(if (null? x) (quote ()) (cdr x))

is CPS transformed into

(null?/k (lambda (v-1) (if v-1 (exit-cont (quote ())) (cdr/k exit-cont x))) x)

The primitive procedures null? and cdr are replaced with continuation version null?/k and cdr/k who take a continuation as an extra first parameter.

river
  • 1,028
  • 6
  • 16
  • could you please clarify, what is `exit-cont`? Where and how is it defined? Also, it is not clear to me what should happen with the inner `if` in your `null?/k` call. After all we define how `if` is translated into CPS, so using `if` in the translation of `if` seems to be circular logic? Could you please clarify? – Will Ness Aug 12 '19 at 12:36
  • @WillNess wouldn't that be `halt` if that was the only code or the rest of the program if it isn't? – Sylwester Aug 12 '19 at 23:04