123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- ; Part of Scheme 48 1.9. See file COPYING for notices and license.
- ; Authors: Olivier Danvy, Richard Kelsey, Jonathan Rees
- ; ,open signals escapes
- ; Changes by jar:
- ; Added Uses of Scheme 48's WITH-CONTINUATION primitive, so that unreachable
- ; continuations can be reclaimed by the GC.
- ;
- ; Renamed reset-thunk -> *reset
- ; call/ct -> *shift
- ;
- ; Note: the meta-continuation ought to be thread-specific.
- ; Alternatively, the threads package could be defined in terms of
- ; shift and reset. This would have the advantage of making the threads
- ; package itself re-entrant. It would be nice to rehabilitate the
- ; runnable-threads queue, currently a piece of global state, as local
- ; to a particular invocation of WITH-MULTITASKING.
- ;Date: Wed, 29 Dec 1993 13:54:52 +0100
- ;From: Olivier Danvy <danvy@daimi.aau.dk>
- ;To: jar@martigny.ai.mit.edu
- ;Subject: little Christmas gift
- ;Reply-To: danvy@daimi.aau.dk
- ;
- ;Hi again:
- ;
- ;Here is a contribution for the Scheme48 library: the shift and reset
- ;operators from "Abstracting Control" (LFP90) and "Representing Control"
- ;(MSCS92). In his POPL94 paper, Andrzej Filinski observed that since the
- ;meta-continuation is single-threaded, it can be globalized in a
- ;register. Andrzej has programmed this both in SML and in Scheme. I
- ;only have prettified the Scheme definition a wee bit.
- (define-syntax reset
- (syntax-rules ()
- ((_ ?e) (*reset (lambda () ?e)))))
- (define-syntax shift
- (syntax-rules ()
- ((_ ?k ?e) (*shift (lambda (?k) ?e)))))
- (define *meta-continuation*
- (lambda (v)
- (assertion-violation 'shift "You forgot the top-level reset...")))
- (define *abort
- (lambda (thunk)
- (with-continuation null-continuation ;JAR hack
- (lambda ()
- (let ((val (thunk)))
- (*meta-continuation* val))))))
- (define null-continuation #f)
- (define *reset
- (lambda (thunk)
- (let ((mc *meta-continuation*))
- (call-with-current-continuation
- (lambda (k)
- (begin
- (set! *meta-continuation*
- (lambda (v)
- (set! *meta-continuation* mc)
- (k v)))
- (*abort thunk)))))))
- (define *shift
- (lambda (f)
- (call-with-current-continuation
- (lambda (k)
- (*abort (lambda ()
- (f (lambda (v)
- (reset (k v))))))))))
- ;----------
- ;
- ;Reminder: reset specifies a control delimiter. shift grabs the current
- ;continuation up to the current control delimiter, and reifies it as a
- ;composable procedure. If the procedure is not used, shift has the
- ;effect of aborting up to the current control delimiter.
- ;
- ;Examples:
- ;
- ;(+ 10 (reset (+ 2 3)))
- ;-->
- ;15
- ;
- ;(+ 10 (reset (+ 2 (shift k 3))))
- ;-->
- ;13
- ;
- ;(+ 10 (reset (+ 2 (shift k (k 3)))))
- ;-->
- ;15
- ;
- ;(+ 10 (reset (+ 2 (shift k (+ 100 (k 3))))))
- ;-->
- ;115
- ;
- ;(+ 10 (reset (+ 2 (shift k (+ 100 (k (k 3)))))))
- ;-->
- ;117
- ;
- ;
- ;Other reminder: shift and reset are weaker than Matthias's control and
- ;prompt, in that they can be CPS-transformed.
- ;
- ;Have a happy holiday,
- ;
- ;-- Olivier
- ;
- ;PS: This definition is not unlike David Espinoza's implementation of monadic
- ;effects, ie, it has no interpretive or translation overhead.
- ; JAR's notes:
- ;
- ; ; CWCC defined in terms of SHIFT
- ;
- ; (define cwcc
- ; (lambda (p)
- ; (shift k (k (p (lambda (x)
- ; (shift k1 (k x))))))))
- ;
- ; ; Monads from shift and reset (from Filinski, POPL '94)
- ;
- ; (define (reflect meaning)
- ; (shift k (extend k meaning)))
- ;
- ; (define (reify thunk)
- ; (reset (eta (thunk))))
- ;
- ; Example: nondeterminism monad.
- ;
- ; > (define (eta x) (list x))
- ; > (define (extend f l) (apply append (map f l)))
- ; >
- ; > (define-syntax amb
- ; (syntax-rules () ((amb ?x ?y) (*amb (lambda () ?x) (lambda () ?y)))))
- ;
- ; > (define (*amb t1 t2)
- ; (reflect (append (reify t1) (reify t2))))
- ; >
- ; > (reify (lambda () (amb 1 2)))
- ; '(1 2)
- ; > (reify (lambda () (+ (amb 1 2) 3)))
- ; '(4 5)
- ; >
- ; > (define cwcc call-with-current-continuation)
- ; > (reify (lambda ()
- ; (+ 1 (cwcc (lambda (k)
- ; (* 10 (amb 3 (k 4))))))))
- ; '(31 51)
- ; >
|