bug-guile
[Top][All Lists]
Advanced

[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/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]