From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Kevin Ryde Newsgroups: gmane.lisp.guile.devel Subject: Re: while break and continue Date: Thu, 05 Jun 2003 11:42:46 +1000 Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Message-ID: <878yshe1ux.fsf@zip.com.au> References: <87isrtmhfw.fsf@zip.com.au> <87he79ic44.fsf@zagadka.ping.de> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1054777354 25600 80.91.224.249 (5 Jun 2003 01:42:34 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Thu, 5 Jun 2003 01:42:34 +0000 (UTC) Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Jun 05 03:42:31 2003 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 19Njlv-0006ea-00 for ; Thu, 05 Jun 2003 03:42:31 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.20) id 19NjnE-0002aU-0M for guile-devel@m.gmane.org; Wed, 04 Jun 2003 21:43:52 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.20) id 19Njmk-00025k-Gw for guile-devel@gnu.org; Wed, 04 Jun 2003 21:43:22 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) id 19Njmf-0001sb-P9 for guile-devel@gnu.org; Wed, 04 Jun 2003 21:43:18 -0400 Original-Received: from snoopy.pacific.net.au ([61.8.0.36]) by monty-python.gnu.org with esmtp (Exim 4.20) id 19NjmP-0001Qs-Bd for guile-devel@gnu.org; Wed, 04 Jun 2003 21:43:01 -0400 Original-Received: from sunny.pacific.net.au (sunny.pacific.net.au [203.2.228.40]) h551gwKN009930 for ; Thu, 5 Jun 2003 11:42:58 +1000 Original-Received: from wisma.pacific.net.au (wisma.pacific.net.au [210.23.129.72]) by sunny.pacific.net.au with ESMTP id h551gwQg023124 for ; Thu, 5 Jun 2003 11:42:58 +1000 (EST) Original-Received: from localhost (ppp76.dyn228.pacific.net.au [203.143.228.76]) by wisma.pacific.net.au (8.12.9/8.12.9) with ESMTP id h551guYZ016760 for ; Thu, 5 Jun 2003 11:42:56 +1000 (EST) Original-Received: from gg by localhost with local (Exim 3.35 #1 (Debian)) id 19NjmB-0005II-00; Thu, 05 Jun 2003 11:42:47 +1000 Original-To: guile-devel@gnu.org Mail-Copies-To: never User-Agent: Gnus/5.090019 (Oort Gnus v0.19) Emacs/21.2 (gnu/linux) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Developers list for Guile, the GNU extensibility library List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: main.gmane.org gmane.lisp.guile.devel:2500 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.devel:2500 Marius Vollmer writes: > > you shouldn't use procedure->memoizing-macro (use > define-macro instead) and that you inject literal procedures into the > expanded code. Ah right, yep. New code and prospective documentation below. The code is still pretty ugly, I suppose that's what you get for non-local exits :-). Maybe should have a caveat in the docs about style, to discourage their use. I wonder if the value parameter for break should be optional, and have while return unspecified when not given. That might be a reasonably common usage. Unless the whole thing is emulating some established convention. Incidentally, where would be a good place to put some tests? syntax.test maybe, or a new file? (define-macro (while cond . body) (let ((break-key (gensym " while break-key")) (continue-key (gensym " while continue-key"))) `(catch ',break-key (lambda () (do ((break (lambda (value) (throw ',break-key value))) (continue (lambda () (throw ',continue-key)))) ((not (catch ',continue-key (lambda () ,(if (null? body) cond ;; avoid some code if body empty `(and ,cond (begin ,@body #t)))) (lambda args #t)))))) (lambda (key value) value)))) - syntax: while cond body ... Run a loop executing BODY while COND is true. COND is tested at the start of each iteration, so if it's `#f' the first time then BODY is not executed at all. The return value is unspecified. Within `while' two additional bindings are provided, and can be used from both COND and BODY. - Scheme Procedure: break value Break out of the `while' form, and have it return the given VALUE. - Scheme Procedure: continue Abandon the current iteration, and continue with the next. Ie. go to the top of the loop, test COND again, etc. Each `while' provides separate `break' and `continue' procedures, and they operate on that `while'. So for instance when `while' loops are nested the outer `break' can be used from within the inner loop to get all the way out. (while (test1) (let ((outer-break break)) (while (test2) (if (something) (outer-break #f))))) Note that each `break' and `continue' procedure can only be used within the dynamic extent of their corresponding `while'. Once the `while' has been exited their behaviour is unspecified. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://mail.gnu.org/mailman/listinfo/guile-devel