From: Gerald Smith
Subject: Continuations in CL
Date: 
Message-ID: <5ma7rb$m5t$1@mhafc.production.compuserve.com>
Does anyone out there have experience using Paul Graham's macros
from chapter 20 of the book titled "On Lisp"

Those six macros allow *most* of the functionality of Scheme
"continuations" to be ported to Common Lisp.

I want to do opportunistic backtracking in CL, without going through
all the hassle that would occur if I did not have access to continuations.

Speed of execution is not a consideration, because I plan to convert
all the continuations to their faster running counterparts, once the
continuation version is up and running.

I feel if someone could show me how to use Paul's macros
to convert the Scheme code below to its CL version, then I should
be able to do subsequent conversions on my own.

The code below is similar to CL's 'dotimes' loop - - I have no
interest in it other than learning how to use the macros in order
to convert it to CL.

For the life of me, I can't convert it, no matter how much I re-read
the books.

; Scheme code - - load into MacGambit or MacScheme
;*******************************************

(define first  (lambda (n) (car n)))
(define second  (lambda (n) (cadr n)))
(define call/cc  call-with-current-continuation)
(define print  (lambda (arg) (display arg) (newline)))

(define attempt
  (lambda (n)
    (print "Likewise this message")
    (let  ((receiver  (lambda (proc) (list n proc) )))
      (call/cc receiver) )))

(define countdown
  (lambda (n)
    (newline)
    (print "This message only appears once")
    (let ((pair (attempt n)))
      (let ( (v (first pair))
             (returner (second pair)))
        (print v)
        (if (positive? v)
            (returner (list (- v 1) returner))
            (print "Blastoff"))
        (newline)
        (newline)) )))

;*******************************************
; End of code


Running countdown on MacGambit Scheme (free) produces this printout

: (countdown 3)

This message only appears once
Likewise this message
3
2
1
0
Blastoff


#f

: 


The colon character is the prompt in the MacGambit version of Scheme.

The last  #f  is just the returned value of the program.

The first four functions are not really necessary, they just improve the readability of the program for those of us who are used to Common Lisp.


Gerald
From: Rolf-Thomas Happe
Subject: Re: Continuations in CL
Date: 
Message-ID: <r5enaq58o2.fsf@xtreme.mathematik.uni-freiburg.de>
In article <············@mhafc.production.compuserve.com> Gerald Smith
 <··········@CompuServe.COM> writes:

[...]
   I feel if someone could show me how to use Paul's macros
   to convert the Scheme code below to its CL version, then I should
   be able to do subsequent conversions on my own.
[...]

My first reply apparently didn't come through, so I'll try for a 
second time.

First & explanatory step: translate your Scheme example by passing
 continuations explicitely.

(defun attempt* (k n)
  (print "Likewise this message")
  (funcall k n k))

(defun countdown* (n)
  (format t "~%This message only appears once~%")
  (let ((k #'(lambda (n k)
	       (print n)
	       (if (plusp n)
		   (funcall k (- n 1) k)
		   (format t "~%Blast off~%~%")))))
    (attempt* k n)))


Try (COUNTDOWN* 3) -- it works (I do hope it does :).

Second step: rewrite this using Paul Graham's macros.

(=defun attempt (n)
   (print "Likewise this message")
   (=values n (=funcall #'(lambda (cc) cc))))

(=defun countdown (n)
  (terpri)
  (print "This message only appears once")
  (=bind (n k) (attempt n)
    (print n)
    (if (plusp n)
	(funcall k (- n 1) k)
        (format t "~%Blast off~%~%"))))

I believe that this is an application of the cp macros somewhat beyond
the intentions of the author, but it works anyway (tested in CLISP).

rthappe

PS: as for the intentions of the author. If (in `On Lisp') you examine
the implementation of threads (chapter 21), then you'll notice that,
as far as the examples go (BARBARIANS), you could remove all the 
=s (e.g. =DEFUN --> DEFUN) without changing the behaviour of 
the program (that's obvious since there is no =BIND in the whole 
program, which means that all the time it's simply #'IDENTITY which
is passed around as continuation).