在 2013-4-6 AM8:53,"Ian Price" 写道: > > Nala Ginrut writes: > > > +@deffn {Scheme Procedure} call/ec proc > > +'ec' stands for escape-continuation, or so-called 'one-shot' continuation. > > +@var{call/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}. > > +@end 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. > > > +@deffn {Scheme Syntax} let/ec k body > > +Equivalent to (call/ec (lambda (k) body ...)). > > +@end deffn > Missing ellipses in the function prototype. In Texinfo, you should be > using @dots{} rather than three periods for ellipses. > > > +@example > > +(use-module (ice-9 control)) > > + > > +(call/ec (lambda (return) > > + (return 123))) > > + > > +(let/ec return (return 123)) > > +@end 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"