>>>> "Hrvoje" == Hrvoje Niksic
<hniksic(a)srce.hr> writes:
Hrvoje> Can you give two or three simple examples of call/cc usage?
I assume you mean code---I enumerated some applications in previous
posts. Note that any code using catch/throw is also an example for
call/cc, but the reverse does not hold.
Here's an implementation of coroutines, courtesy of Matthias Blume,
Princeton.
(define (new-coroutine)
(let ((x '()))
(lambda (cmd)
(if cmd
(set! x cmd)
(x #f)))))
(define (init-coroutine! c proc . args)
(c (lambda (ign)
(apply proc args))))
(define (transfer! from to)
(call-with-current-continuation
(lambda (c)
(from c)
(to #f))))
Here's an implementation of generators from the Scheme 48
distribution.
; Copyright (c) 1993, 1994 by Richard Kelsey and Jonathan Rees.
; Copyright (c) 1996 by NEC Research Institute, Inc. See file COPYING.
; Internal variable representing the failure stack.
(define (fail) (*fail*))
(define *fail* (lambda () (error "You didn't do (init).")))
; For the alternation operator, Icon's a | b or McCarthy's (amb a b),
; we write (either a b).
(define-syntax either
(syntax-rules ()
((either) (fail))
((either x) x)
((either x y ...)
(%either (lambda () x) (lambda () (either y ...))))))
(define (%either thunk1 thunk2) ;Macro auxiliary
(saving-failure-state
(lambda (restore)
((call-with-current-continuation
(lambda (k)
(set! *fail*
(lambda ()
(restore)
(k thunk2)))
thunk1))))))
(define (saving-failure-state proc)
(let ((save *fail*))
(proc (lambda () (set! *fail* save)))))
; (one-value x) is Prolog's CUT operator
(define-syntax one-value
(syntax-rules ()
((one-value x) (%one-value (lambda () x)))))
(define (%one-value thunk)
(saving-failure-state
(lambda (restore)
(let ((value (thunk)))
(restore)
value))))
; (all-values a) returns a list of all the possible values of the
; expression a. Prolog calls this "bagof"; I forget what Icon calls it.
(define-syntax all-values
(syntax-rules ()
((all-values x) (%all-values (lambda () x)))))
(define (%all-values thunk)
(let ((results '()))
(either (let ((new-result (thunk)))
(set! results (cons new-result results))
(fail))
(reverse results))))
; Generate all the members of list l. E.g.
; (all-values (+ (member-of '(10 20 30)) (member-of '(1 2 3))))
; => '(11 12 13 21 22 23 31 32 33)
(define (member-of l)
(if (null? l)
(fail)
(either (car l) (member-of (cdr l)))))
; Crufty initialization hack that allows you to type failing
; expressions at the R-E-P loop (if there is an R-E-P loop). E.g. try
; evaluating the sequence
; (either 1 2)
; (fail)
; (+ (fail) 10)
(define (init)
(set! *fail* #f) ;for GC purposes
(either 'initialized
(let loop ()
(either 'failed (loop)))))
(display "Type (init) at the read-eval-print loop.")
(newline)
An implementation of an exception system, documentation is in
ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/prop/exceptions.ss
Documentation is in:
ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/prop/exceptions
Here's a (not-so-simple) implementation of control representation,
also from the Scheme 48 implementation:
; no copyright notice
; ,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(a)daimi.aau.dk>
;To: jar(a)martigny.ai.mit.edu
;Subject: little Christmas gift
;Reply-To: danvy(a)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)
(error "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)
; >
--
Cheers =8-} Chipsy
Friede, Völkerverständigung und überhaupt blabla