[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: shift and reset in ice-9 control
From: |
Wolfgang J Moeller |
Subject: |
Re: shift and reset in ice-9 control |
Date: |
Sat, 2 Apr 2011 16:40:12 +0200 (CEST) |
On Wed, 30 Mar 2011, Andy Wingo wrote:
> On Mon 21 Mar 2011 02:31, Wolfgang J Moeller <address@hidden> writes:
>[...]
> > However, I don't like it anymore, since I seem to have learned
> > that this "direct implementation" doesn't at all play well
> > with the use of call/cc within the <body>s, while the call/cc-based
> > implementations of shift/reset appear to do so.
> >
> > I've yet to find out why the latter work "better", and if there's
> > a remedy possible using something like with-continuation-barrier ...
>
> Can you give some examples? In Guile things should work fine, AIUI.
>
> In the future (i.e., 2.2), I would like to change continuations to
> capture just the Scheme stack, and optionally delimit their extent to a
> prompt. I recommend Flatt et al's ICFP 2007 paper for a discussion.
Interesting, but only in order to re-inspect "my" DYNAMIC-WIND,
whose interactions with CALL-WITH-PROMPT and ABORT-TO-PROMPT
I've not even tested yet.
No, I'm not concerned with the implementation of the primitives,
but with an attempt of mine to express a co-routine linkage using
reset/shift (would you know of an example in the literature?).
A stripped-down example goes like this:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (f1 ret)
(let ((c #f))
(do ((n 0 (+ n 1)))
((> n 2) #f)
(display n) ; at start of new line
(case n
((0) (ret n))
((1) (ret (call/cc (lambda (k)
(set! c k)
-1))))
(else (c n))))))
;;
(let ((dc #f)
(saymax 5))
;;
(define (return-saving-dc v)
(shift d (begin
(set! dc d)
v)))
;;
(define (say . vs)
(set! saymax (- saymax 1))
(if (negative? saymax) (error "saymax < 0"))
(for-each display vs) (newline))
;;
(say "#0: " (reset (f1 return-saving-dc)))
;;
(say "#1: " (dc "ignored.1"))
(say "#2: " (dc "ignored.2"))
(say "#3: " (dc "ignored.3"))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Think of (f1) as a sort-of co-routine and of (return-saving-dc)
as my best attempt to save co-routine state using reset/shift only.
Using the "direct" implementaion of reset/shift (mine seems to agree
with Flatt et.al.), it goes into a loop since (dc "ignored.2")
makes (f1) restore the full continuation that makes (dc "ignored.1")
return one more time - "dc" isn't so "delimited" after all.
Remarkably, the example works out differently (no loop) with either
call/cc-based implementation of reset/shift that I know of (one using
a "meta-continuation", the other a continuation stack) - as I understand it,
this comes from the delimited continuations always returning via another
full continuation that was captured at invocation time.
Maybe it's a "discovery" that the different implementations of reset/shift
do have observably different outcomes ...
And because I had first played with call/cc-based reset/shift,
I had the impression that it's indeed possible to do co-routine linkage
using these primitives w/o requiring call/cc. Then there came GUILE V2
and made me try out the "direct" way, plus I (incidentally) had call/cc
(only for _local_ transfer of control, just like in the example)
in one of my co-routines ... that's why I (at the moment) dislike
the "direct" implementation.
I haven't yet found a place where adding (with-continuation barrier)
[as in GUILE V2.0.0, at least] could help me; next thing was to think hard
about the potential of (dynamic-wind).
===
Some confusing observations about a "borderline" case
(evaluation of (define) determines "definition"-property
of the next statement) at GUILE V2's toplevel:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(begin
(define dummy1
(eval
;;
'(defmacro macro-case clauses
(let lp ((cs clauses))
(if (null? cs)
'(define dummy2 #f)
(if (or (and (symbol? (caar cs))
(eq? (caar cs) 'else))
(eval (caar cs) (interaction-environment)))
(cons 'begin (cdar cs))
(lp (cdr cs))))))
;;
(interaction-environment)))
)
;;
(macro-case
(#f
(define something #t)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(That's just the traditional _structure_ of my prelude,
intended to have nothing but definitions at the toplevel).
Depending upon what I do with this snippet (auto-compile, load vs. include),
it sometimes gets accepted by GUILE V2.0.0:
auto,include auto,load noauto,include noauto,load
---------------------------------------------------------------------------
@toplevel Error Error Error OK
surroundes by
BEGIN Error Error Error Error
EVAL-WHEN OK OK OK Error
To add to the weirdness, removing the (supposedly redundant) BEGIN
around (DEFINE dummy1) reverses most of the outcomes ...
Not a serious problem - just confusing!
===
Best regards,
Wolfgang J. Moeller, Tel. +49 551 47361, wjm<AT>heenes.com
37085 Goettingen, Germany | Disclaimer: No claim intended!
http://www.wjmoeller.de/ -+-------- http://www.heenes.com/
- Re: shift and reset in ice-9 control,
Wolfgang J Moeller <=