guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Move let/ec to top-level


From: Nala Ginrut
Subject: Re: [PATCH] Move let/ec to top-level
Date: Sat, 6 Apr 2013 10:53:48 +0800


在 2013-4-6 AM8:53,"Ian Price" <address@hidden>写道:
>
> Nala Ginrut <address@hidden> writes:
>
> > address@hidden {Scheme Procedure} call/ec proc
> > +'ec' stands for escape-continuation, or so-called 'one-shot' continuation.
> > address@hidden/ec} is equivalent to call-with-escape-continuation.
> > +A continuation obtained from call/ec is actually a kind of prompt. @var{call/ec}
> > +is often an easy replacement for @var{call/cc} to improve performance.
> > +More details read @uref{http://www.cs.indiana.edu/~bruggema/one-shots-abstract.html,
> > +Representing control in the presence of one-shot continuations}.
> > address@hidden deffn
> This isn't any good. It doesn't tell us what an escape continuation is,
> it doesn't tell us how to use it, and it only hints at why you should
> use them. Yeah, if you know what a continuation is "one-shot
> continuation" isn't going to be a surprising definition, but we can do
> better than that in Guile's manual.
>
> Here is something closer to how I envision this section should be
> written. I have not taken the liberty of texinfoifying it.
>
> ----
> Often in Guile, you do not need the full unrestricted power of first
> class continuations, you just want an escape.  For example, to break
> out of multiplying a list of numbers, you might write
>
>   (define (product list)
>     (call-with-current-continuation
>       (lambda (break)
>         (let loop ((list list) (product 1))
>           (cond ((null? list) product)
>                 ((zero? (car list)) (break 0))
>                 (else (loop (cdr list) (* (car list) product))))))))
>
> In this case, it can be more transparent, and more efficient, to use a
> restricted form of continuation, which we refer to as an escape (or
> one-shot) continuation, that only permits you to call it once from to
> escape from inside the body of the function.
>
>
> Scheme Procedure call-with-escape-continuation proc
> Scheme Procedure call/ec proc
>
> Capture the current escape-only continuation, and call proc with this
> continuation as its argument.  The return value(s) of this _expression_
> are the value(s) returned by proc, or, the arguments passed to the
> escape continuation if it is invoked.
>
> If the escape continuation is invoked more than once, or it is invoked
> after proc has returned, it is an $error.
>
> call/ec is an alias for call-with-escape-continuation
> ----
>
> I didn't check what error actually gets returned, so that bit needs
> filled in.
>
> In various parts of the manual, we mention that prompts should be used
> for the situation of escapes.  We should probably hunt those down and
> replace those with recommendations to use call/ec or let/ec.
>
> > address@hidden {Scheme Syntax} let/ec k body
> > +Equivalent to (call/ec (lambda (k) body ...)).
> > address@hidden deffn
> Missing ellipses in the function prototype. In Texinfo, you should be
> using @dots{} rather than three periods for ellipses.
>
> > address@hidden
> > +(use-module (ice-9 control))
> > +
> > +(call/ec (lambda (return)
> > +           (return 123)))
> > +
> > +(let/ec return (return 123))
> > address@hidden example
> Not a particularly convincing example, maybe drop it?
>
> > +
> > +(define %call/ec-prompt
> > +  (make-prompt-tag))
> You don't use this, so you can remove it.  If your intent was to reuse
> the prompt so that you didn't have to do a gensym each time, beware,
> this won't give the correct semantics for call/ec.
>
> e.g.
> (call/ec
>   (lambda (outer)
>     (call/ec
>       (lambda (inner)
>         (outer #f)))
>     #t))
>
> will return #t rather than #f
>
> > +(define-syntax-rule (call/ec proc)
> define rather than define-syntax-rule
>
> > +  ;; aka. `call-with-escape-continuation'
> Rather than an aka in a comment, maybe we should export this.  In the
> example documentation given above, I've assumed this.
>
> > +  (let ((tag (make-prompt-tag)))
> > +    (call-with-prompt
> > +     tag
> > +     (lambda ()
> > +       (proc (lambda args (apply abort-to-prompt args))))
> you are not aborting to the tag, but to the first of the args
> (the dangers of copy-paste)
>
> > +     (lambda (_ . args)
> > +       (apply values args)))))
> > +
> > +(define-syntax-rule (let/ec k e e* ...)
> > +  ;; aka. `let-escape-continuation'
> Rather let-with-escape-continuation than let-escape-continuation, since
> it's the same convention as with call/ec and call/cc (not that it
> matters if we don't export it)
>
> As an aside, we don't have a corresponding let/cc, but I suspect most
> uses of it in practice would be replaced by let/ec.
>
> > -(define-syntax-rule (let/ec k e e* ...)           ; TODO: move to core
> > -  (let ((tag (make-prompt-tag)))
> > -    (call-with-prompt
> > -     tag
> > -     (lambda ()
> > -       (let ((k (lambda args (apply abort-to-prompt tag args))))
> > -         e e* ...))
> > -     (lambda (_ res) res))))
> > -
> > -
> >  (define %future-prompt
> >    ;; The prompt futures abort to when they want to wait for another
> >    ;; future.
> This isn't the only definition of let/ec in the Guile source code. I see
> definitions in module/language/tree-il/peval.scm and
> module/sxml/match.scm (as an aside, I notice match.scm makes the prompt
> reuse mistake you almost did)
>

Yes, but the original purpose is to move the "futures" one.
And I apologize for the redundant things. :-(

> --
> Ian Price -- shift-reset.com
>
> "Programming is like pinball. The reward for doing it well is
> the opportunity to do it again" - from "The Wizardy Compiled"


reply via email to

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