From: Marius Vollmer <mvo@zagadka.ping.de>
Cc: guile-user@gnu.org
Subject: Re: Continuations: possible newbie question
Date: 19 Dec 2002 01:41:24 +0100 [thread overview]
Message-ID: <87n0n2hmbv.fsf@zagadka.ping.de> (raw)
In-Reply-To: <20021218175155.B25665@metro.immute.net>
Matt Hellige <matt@immute.net> writes:
> On the other hand, I'll probably still not end up using this technique
> to implement my call-backs, given the performance penalties and so on.
> I hope I can just shuffle things around a bit in my native code...
I would not worry about performance too early. If you invoke one
continuation for every key press by the user, that should be no
problem.
Here is a little Gtk+ program that shows off continuations. I still
find it quite instructive...
;; This is an example of how to use continuations with the Gtk event
;; loop. It implements a dialog box that looks to the programmer like
;; it was modal, and to the user like it was non-modal. The function
;; `yes-or-no?' that implements this dialog box only returns to the
;; caller when the user has aswered the dialog. The user however can
;; pop up any number of these dialog boxes and answer them in any
;; order he likes. The main application stays alive as well.
(use-modules (gtk gtk))
;; The callbacks that have been delayed
(define callbacks '())
;; Our own event-loop. We remove the callbacks before invoking them
;; so that we don't get confused when the callback reenters the
;; event-loop.
(define (event-loop)
(cond
((not (null? callbacks))
(let ((c (car callbacks)))
(set! callbacks (cdr callbacks))
(c)
(event-loop)))
((not (zero? (gtk-main-iteration)))
(event-loop))))
;; Connect to a signal and arrange for PROC to be consed onto
;; CALLBACKS when the signal is emitted.
(define (gtk-signal-connect-delayed obj sig proc)
(gtk-signal-connect obj sig
(lambda () (set! callbacks (cons proc callbacks)))))
;; Now for the continuation part. To implement the non-modal dialog box
;; that can be used from your code like a modal one, we save the
;; continuation of the YES-OR-NO? invokation and reenter the event-loop
;; (after popping up the window). When a button has been clicked, we
;; destroy the window and invoke the saved continuation with the
;; appropriate return value.
(define (yes-or-no? title)
(call-with-current-continuation
(lambda (cont)
;; Now CONT is the part of the program that receives our
;; return value.
(let* ((d (gtk-window-new 'dialog))
(v (gtk-vbox-new #f 0))
(h (gtk-hbox-new #t 0))
(l (gtk-label-new title))
(s (gtk-hseparator-new))
(y (gtk-button-new-with-label "Yes"))
(n (gtk-button-new-with-label "No"))
(answer (lambda (val)
(gtk-widget-destroy d)
;; Here we return to our caller after the
;; dialog has been destroyed.
(cont val))))
(gtk-container-add d v)
(gtk-box-pack-start v l #f #f 0)
(gtk-box-pack-start v s #f #f 0)
(gtk-box-pack-start v h #f #f 0)
(gtk-box-pack-start h y #f #f 0)
(gtk-box-pack-start h n #f #f 0)
(gtk-widget-show-all d)
;; Bind ANSWER to the "clicked" signals of the action
;; buttons.
(gtk-signal-connect-delayed y "clicked" (lambda () (answer #t)))
(gtk-signal-connect-delayed n "clicked" (lambda () (answer #f)))
;; Reenter the event-loop. You can think of this as a goto.
(event-loop)))))
(define w (gtk-window-new 'toplevel))
(define b (gtk-button-new-with-label "Ok!"))
(gtk-container-add w b)
(gtk-signal-connect-delayed
b "clicked"
(let ((i 0))
(lambda ()
(set! i (1+ i))
;; capture I in a local environment so that nobody can alter
;; it while YES-OR-NO? does its thing.
(let ((i i))
;; Use YES-OR-NO? as if it were a modal dialog.
(pk i (yes-or-no? (string-append (number->string i)
": Really?")))))))
(gtk-signal-connect w "destroy" gtk-exit)
(gtk-widget-show b)
(gtk-widget-show w)
(event-loop)
--
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3 331E FAF8 226A D5D4 E405
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
next prev parent reply other threads:[~2002-12-19 0:41 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-12-18 17:27 Continuations: possible newbie question Thien-Thi Nguyen
2002-12-18 18:14 ` Matt Hellige
2002-12-18 20:04 ` Neil Jerram
2002-12-18 23:51 ` Matt Hellige
2002-12-19 0:41 ` Marius Vollmer [this message]
2002-12-19 2:42 ` Matt Hellige
-- strict thread matches above, loose matches on Subject: below --
2002-12-18 18:42 Thien-Thi Nguyen
2002-12-18 0:14 Matt Hellige
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87n0n2hmbv.fsf@zagadka.ping.de \
--to=mvo@zagadka.ping.de \
--cc=guile-user@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).