* manipulating continuations
@ 2011-02-12 8:35 Tomtom
0 siblings, 0 replies; 8+ messages in thread
From: Tomtom @ 2011-02-12 8:35 UTC (permalink / raw)
To: guile-user
Hello list
First of all, I'm new to scheme and guile - started using them a few
days ago for a project. So here we go: this is the bit of code that
causing me troubles:
(define (foo)
(call/cc
(lambda (return)
(display "first part")
(newline)
(call/cc
(lambda (cont)
(return cont)))
(display "second part")
(newline))))
Basically, I use call/cc to stop the procedure foo after printing "first
part" and return a continuation. Then, if I call this continuation it
prints "second part" and ends. To test this code, I did this:
guile> (define c (foo))
first part
guile> (c)
second part
yay, it works. But now, what if I want to run the continuation directly,
rather than storing it and calling it later ? This is what I get:
guile> ((foo))
first part
second part
Backtrace:
In current input:
15: 0* [#<unspecified>]
<unnamed port>:15:1: In expression ((foo)):
<unnamed port>:15:1: Wrong type to apply: #<unspecified>
ABORT: (misc-error)
There. I don't understand why I get this error message.
Cheers
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread
* manipulating continuations
@ 2011-02-12 14:10 Thomas Girod
2011-02-12 15:43 ` Andy Wingo
0 siblings, 1 reply; 8+ messages in thread
From: Thomas Girod @ 2011-02-12 14:10 UTC (permalink / raw)
To: guile-user
Hello list
I'm new to scheme and guile - started using them a few
days ago for a project. So here we go: this is the bit of code that
causing me troubles:
(define (foo)
(call/cc
(lambda (return)
(display "first part")
(newline)
(call/cc
(lambda (cont)
(return cont)))
(display "second part")
(newline))))
Basically, I use call/cc to stop the procedure foo after printing "first
part" and return a continuation. Then, if I call this continuation it
prints "second part" and ends. To test this code, I did this:
guile> (define c (foo))
first part
guile> (c)
second part
yay, it works. But now, what if I want to run the continuation directly,
rather than storing it and calling it later ? This is what I get:
guile> ((foo))
first part
second part
Backtrace:
In current input:
15: 0* [#<unspecified>]
<unnamed port>:15:1: In expression ((foo)):
<unnamed port>:15:1: Wrong type to apply: #<unspecified>
ABORT: (misc-error)
There. I don't understand why I get this error message.
Cheers
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: manipulating continuations
2011-02-12 14:10 manipulating continuations Thomas Girod
@ 2011-02-12 15:43 ` Andy Wingo
2011-02-12 16:40 ` Keith Wright
[not found] ` <1297887196-sup-8146@cresylol.hd.free.fr>
0 siblings, 2 replies; 8+ messages in thread
From: Andy Wingo @ 2011-02-12 15:43 UTC (permalink / raw)
To: Thomas Girod; +Cc: guile-user
Hi Thomas,
On Sat 12 Feb 2011 15:10, Thomas Girod <girodt@gmail.com> writes:
> (define (foo)
> (call/cc
> (lambda (return)
> (display "first part")
> (newline)
> (call/cc
> (lambda (cont)
> (return cont)))
> (display "second part")
> (newline))))
>
> guile> (define c (foo))
> first part
> guile> (c)
> second part
>
> yay, it works. But now, what if I want to run the continuation directly,
> rather than storing it and calling it later ? This is what I get:
>
> guile> ((foo))
> first part
> second part
>
> Backtrace:
> In current input:
> 15: 0* [#<unspecified>]
In this expression, `foo' has returned twice. The first time it
returned a continuation, which was applied. The second time it returned
whatever `newline' returned: the unspecified value. Applying the
unspecified value failed.
If you use Guile 1.9/2.0, partial continuations behave more in the way
you were thinking of:
(use-modules (ice-9 control))
(define (foo)
(% (begin
(display "first part\n")
(abort)
(display "second part\n"))
(lambda (cont)
;; abort jumps back here, to the handler. return the partial
;; continuation.
cont)))
scheme@(guile-user)> (foo)
first part
$1 = #<partial-continuation 29dede0>
scheme@(guile-user)> ($1)
second part
scheme@(guile-user)> ((foo))
first part
second part
scheme@(guile-user)>
Have fun with Guile,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: manipulating continuations
2011-02-12 15:43 ` Andy Wingo
@ 2011-02-12 16:40 ` Keith Wright
2011-02-12 17:16 ` Andy Wingo
[not found] ` <1297887196-sup-8146@cresylol.hd.free.fr>
1 sibling, 1 reply; 8+ messages in thread
From: Keith Wright @ 2011-02-12 16:40 UTC (permalink / raw)
To: wingo; +Cc: guile-user
> From: Andy Wingo <wingo@pobox.com>
> Cc: guile-user@gnu.org
>
> Hi Thomas,
>
> In this expression, `foo' has returned twice. The first time it
> returned a continuation, which was applied. The second time it returned
> whatever `newline' returned: the unspecified value. Applying the
> unspecified value failed.
This first part is good.
It explains that you have evaluated ((newline))
on the second call.
> If you use Guile 1.9/2.0, partial continuations behave more in the way
> you were thinking of:
>
> (use-modules (ice-9 control))
>
> (define (foo)
> (% (begin
> (display "first part\n")
> (abort)
> (display "second part\n"))
> (lambda (cont)
> ;; abort jumps back here, to the handler. return the partial
> ;; continuation.
> cont)))
This is not Scheme and should be ignored by anyone
who is new to Scheme. I have been using Scheme,
off and on, for decades but I can't read this program.
What is (% ...)? What is a "partial continuation"?
Has Guile gone off into left field, never to return?
Can we continue from R5RS or R6RS?
-- Keith
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: manipulating continuations
2011-02-12 16:40 ` Keith Wright
@ 2011-02-12 17:16 ` Andy Wingo
2011-02-12 20:56 ` Thien-Thi Nguyen
0 siblings, 1 reply; 8+ messages in thread
From: Andy Wingo @ 2011-02-12 17:16 UTC (permalink / raw)
To: Keith Wright; +Cc: guile-user
On Sat 12 Feb 2011 17:40, Keith Wright <kwright@keithdiane.us> writes:
> What is (% ...)? What is a "partial continuation"?
% sets up a prompt.
http://www.gnu.org/software/guile/docs/master/guile.html/Prompts.html
http://en.wikipedia.org/wiki/Delimited_continuation
http://www.ccs.neu.edu/scheme/pubs/pldi93-sitaram.pdf
> Has Guile gone off into left field, never to return?
Hardly, these control operators are nearly a quarter of a century old...
> Can we continue from R5RS or R6RS?
R5RS and R6RS's continuations are not generally useful for making
abstractions that compose well together. I would not recommend them to
anyone.
Regards,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: manipulating continuations
2011-02-12 17:16 ` Andy Wingo
@ 2011-02-12 20:56 ` Thien-Thi Nguyen
2011-02-12 21:33 ` Andy Wingo
0 siblings, 1 reply; 8+ messages in thread
From: Thien-Thi Nguyen @ 2011-02-12 20:56 UTC (permalink / raw)
To: Andy Wingo; +Cc: guile-user
() Andy Wingo <wingo@pobox.com>
() Sat, 12 Feb 2011 18:16:20 +0100
R5RS and R6RS's continuations are not generally useful for making
abstractions that compose well together. I would not recommend them to
anyone.
Are you saying Guile 2.0 breaks code that uses these traditional
continuations (successfully, in previous Guile versions)? I think
the OP example should be in NEWS, if so, to avoid a surprise.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: manipulating continuations
2011-02-12 20:56 ` Thien-Thi Nguyen
@ 2011-02-12 21:33 ` Andy Wingo
0 siblings, 0 replies; 8+ messages in thread
From: Andy Wingo @ 2011-02-12 21:33 UTC (permalink / raw)
To: Thien-Thi Nguyen; +Cc: guile-user
On Sat 12 Feb 2011 21:56, Thien-Thi Nguyen <ttn@gnuvola.org> writes:
> () Andy Wingo <wingo@pobox.com>
> () Sat, 12 Feb 2011 18:16:20 +0100
>
> R5RS and R6RS's continuations are not generally useful for making
> abstractions that compose well together. I would not recommend them to
> anyone.
>
> Are you saying Guile 2.0 breaks code that uses these traditional
> continuations (successfully, in previous Guile versions)?
No, I am not saying that. Tom's code works the same on Guile 1.8 and on
1.9/2.0.
Regards,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: manipulating continuations
[not found] ` <1297887196-sup-8146@cresylol.hd.free.fr>
@ 2011-02-17 11:08 ` Andy Wingo
0 siblings, 0 replies; 8+ messages in thread
From: Andy Wingo @ 2011-02-17 11:08 UTC (permalink / raw)
To: Thomas Girod; +Cc: guile-user
Hi Thomas,
Thanks for playing around with prompts! We use them internally in
Guile, but as they are not yet a standard part of Scheme, there's less
awareness of what they're up to.
Your example brings up an interesting point:
On Wed 16 Feb 2011 21:30, Thomas Girod <girodt@gmail.com> writes:
>> (use-modules (ice-9 control))
>> (define (foo)
>> (% (begin
>> (display "first part\n")
>> (abort)
>> (display "second part\n")
>> (abort)
>> (display "third time\n"))
>> (lambda (cont) cont)))
>
> scheme@(guile-user)> (foo)
> first part
> $1 = #<partial-continuation 906f5e0>
> scheme@(guile-user)> ($1)
> second part
> module/system/repl/repl.scm:98:4: In procedure with-stack-and-prompt:
> module/system/repl/repl.scm:98:4: Throw to key `vm-error' with args `(vm-run "Too few values returned to continuation" ())'.
What's happening here is that $1, the continuation returned in the first
(abort), does not itself include a prompt.
So when you invoke it again, you are running it without an enclosing
prompt -- so when the second (abort) is called, it finds the next
closest prompt with the default prompt tag (as we did not specify one
explicitly), and that prompt is part of the REPL implementation. It so
happens that the abort handler for the REPL prompt expects at least one
value to be returned to it, via (abort FOO ...); hence this error.
(Though really we should make this error more helpful.)
Why is it implemented this way, you ask? Well it's to preserve tail
recursion in some cases. See the first third of the 2007 paper by
Dybvig, Peyton-Jones, and Sabry, "A monadic framework for delimited
continuations", at http://www.cs.indiana.edu/~dyb/pubs/monadicDC.pdf.
Guile's % (or call-with-prompt) corresponds to the -F- operator.
> I guess I'm having a problem very similar to the previous one I encountered,
> linked to the way prompts are built based on call/cc, right ? Are there any
> ways to solve this ?
Prompts are not actually built on call/cc; and indeed they cannot be.
So! Your real concern was to be able to make coroutines or generators
or something, right? Let's use a tagged prompt, and use the more
primitive call-with-prompt and abort-to-prompt procedures:
(define (coroutine proc)
(let ((tag (make-prompt-tag)))
(define (yield . args)
(apply abort-to-prompt tag args))
(define (handler cont . args)
(define (resume . args)
(call-with-prompt tag
(lambda () (apply cont args))
handler))
(apply values resume args))
(call-with-prompt tag
(lambda () (proc yield))
handler)))
(coroutine
(lambda (yield)
(display "first part\n")
(yield)
(display "second part\n")
(yield)
(display "third time\n")))
first part
$2 = #<procedure resume args>
scheme@(guile-user)> ($2)
second part
$3 = #<procedure resume args>
scheme@(guile-user)> ($3)
third time
Happy hacking,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-02-17 11:08 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-12 14:10 manipulating continuations Thomas Girod
2011-02-12 15:43 ` Andy Wingo
2011-02-12 16:40 ` Keith Wright
2011-02-12 17:16 ` Andy Wingo
2011-02-12 20:56 ` Thien-Thi Nguyen
2011-02-12 21:33 ` Andy Wingo
[not found] ` <1297887196-sup-8146@cresylol.hd.free.fr>
2011-02-17 11:08 ` Andy Wingo
-- strict thread matches above, loose matches on Subject: below --
2011-02-12 8:35 Tomtom
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).