From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Marius Vollmer Newsgroups: gmane.lisp.guile.user Subject: Re: Continuations: possible newbie question Date: 19 Dec 2002 01:41:24 +0100 Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Message-ID: <87n0n2hmbv.fsf@zagadka.ping.de> References: <20021218121410.A24945@metro.immute.net> <20021218175155.B25665@metro.immute.net> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1040258534 25173 80.91.224.249 (19 Dec 2002 00:42:14 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Thu, 19 Dec 2002 00:42:14 +0000 (UTC) Cc: guile-user@gnu.org Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 18OolP-0006Xl-00 for ; Thu, 19 Dec 2002 01:42:11 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18OolA-0004AN-04 for guile-user@m.gmane.org; Wed, 18 Dec 2002 19:41:56 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10.13) id 18Ookl-00048K-00 for guile-user@gnu.org; Wed, 18 Dec 2002 19:41:31 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10.13) id 18Ooki-00045y-00 for guile-user@gnu.org; Wed, 18 Dec 2002 19:41:30 -0500 Original-Received: from dialin.speedway43.dip177.dokom.de ([195.138.43.177] helo=zagadka.ping.de) by monty-python.gnu.org with smtp (Exim 4.10.13) id 18Ookh-00040S-00 for guile-user@gnu.org; Wed, 18 Dec 2002 19:41:27 -0500 Original-Received: (qmail 6028 invoked by uid 1000); 19 Dec 2002 00:41:24 -0000 Original-To: Matt Hellige In-Reply-To: <20021218175155.B25665@metro.immute.net> Original-Lines: 117 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: General Guile related discussions List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: main.gmane.org gmane.lisp.guile.user:1460 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.user:1460 Matt Hellige 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