From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Damien Mattei Newsgroups: gmane.lisp.guile.user Subject: Re: for with break and continue Date: Sun, 4 Sep 2022 14:00:37 +0200 Message-ID: References: <89d7a30c-9a36-00b9-49d1-a28b0d776ce3@abou-samra.fr> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="13511"; mail-complaints-to="usenet@ciao.gmane.io" Cc: guile-user To: Jean Abou Samra Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Sun Sep 04 14:01:52 2022 Return-path: Envelope-to: guile-user@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oUoK0-0003M8-Gh for guile-user@m.gmane-mx.org; Sun, 04 Sep 2022 14:01:52 +0200 Original-Received: from localhost ([::1]:39188 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oUoJz-0008L7-55 for guile-user@m.gmane-mx.org; Sun, 04 Sep 2022 08:01:51 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:44294) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oUoJ6-0008JW-3N for guile-user@gnu.org; Sun, 04 Sep 2022 08:00:57 -0400 Original-Received: from mail-lf1-x12b.google.com ([2a00:1450:4864:20::12b]:43879) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oUoJ1-00081M-Dh for guile-user@gnu.org; Sun, 04 Sep 2022 08:00:55 -0400 Original-Received: by mail-lf1-x12b.google.com with SMTP id v26so9552237lfd.10 for ; Sun, 04 Sep 2022 05:00:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date; bh=lVlTO1yoZkqYDSk/ZgeBa614ZF7aaSa5PT0JxG3n1Qc=; b=LGawiHoVgTVlCrKFm/lBaLPvxXhfUlba5sIQkJEQmKFHzJWXR3GQ+ZYQrBYq0NEywv RkS0KpqnM/JGNJtViUcIz2pSK6DcLzGh+A19fiJXCLtVyejoZ0Ce4XxEjQWhLsMr11vn 8kT+YkVUhP50BSJcV682OttSHvTVGjAj0ePC36wt5/129kOKOxyEWPLC3ZPMDTGTnfuV 0wVKMV0XcWXzFbP40mpJdpkxFsBKjnuze8VOlG5UYcCo5cuPR4LNz/3orPh/n8bR3QPi pnZiVHZkeLLDFaONuyv6ugnA+7rcppqC415sw0wKqRPJZQ4H+1zxcabAdYXPZAQFE5PO ip8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date; bh=lVlTO1yoZkqYDSk/ZgeBa614ZF7aaSa5PT0JxG3n1Qc=; b=JsovrAE43g+6jRCYOJ9eLIVqC5X2w8X2WazlufHyXmVQPAl3At093L9/iN6N1IcQX5 aFKi/ubeDcTvsXkGl+YzBwqUMM/7CB8Neae4ImaQrqFNENtGo8zxS0d9wH9qU+U0G5Mq +XXF2tEPg60AtrdO4ypYrU1o4TRlKLvA9e6aEtjteSdq3zbRRakdI/jKjSb5WiwMg8jP lvDFcYrSMAnkqb8aTyUrA8WmKFs7OIF7ejf/gaP01HSpH4VQFL1QMXtCjQZFe1sNIdFd 00KfIUUr47mCS3iZJCDpxN8ZD6Nv8W/PYwbo+xxjwl0Wtul6K8Y70++2Egeh9aaV/9+7 jSUA== X-Gm-Message-State: ACgBeo3OtsdDXkhdUlIXegnjbhF83S4/xOAeLQWUouLqaZKclOGsi6iF rW25uLN5qVkbZfR6F6dGnPxIBaHTtaItXs22G4M= X-Google-Smtp-Source: AA6agR5I4d493UUf9gumSjNjd8JtRjO6aQ0DM8siOl+yHfBHMt2PtoQbM/ShXPaxYDpgr2QpZpfH02Eav6pm2Jx2GWw= X-Received: by 2002:a05:6512:3b87:b0:494:9a8d:f74f with SMTP id g7-20020a0565123b8700b004949a8df74fmr5301721lfv.8.1662292849252; Sun, 04 Sep 2022 05:00:49 -0700 (PDT) In-Reply-To: <89d7a30c-9a36-00b9-49d1-a28b0d776ce3@abou-samra.fr> Received-SPF: pass client-ip=2a00:1450:4864:20::12b; envelope-from=damien.mattei@gmail.com; helo=mail-lf1-x12b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.io gmane.lisp.guile.user:18566 Archived-At: yes very good then break si not overwritten, using module, i do not know if modules is finally standardised in R6RS, and in guile? a few problem with module i hope to fix it later but it works with your example, not sure let/ec is standart? i will continue later.... Damien On Sun, Sep 4, 2022 at 12:44 PM Jean Abou Samra wrote: > Le 04/09/2022 =C3=A0 11:54, Damien Mattei a =C3=A9crit : > > i try to make a for with break and continue the way C language do it, i > > works with break but if i add a continue feature i then loose the break > > feature, here is my code: > > (define-syntax for/bc > > > > (lambda (stx) > > (syntax-case stx () > > ((kwd (init test incrmt) body ...) > > > > (with-syntax > > ((BREAK (datum->syntax #'kwd 'break))) > > > > #'(call/cc > > (lambda (escape) > > (let-syntax > > ((BREAK (identifier-syntax (escape)))) > > init > > (let loop () > > (when test > > > > (with-syntax > > ((CONTINUE (datum->syntax #'kwd 'continue))) > > > > #'(call/cc > > (lambda (next) > > (let-syntax > > ((CONTINUE (identifier-syntax (next)))) > > body ...))) > > > > incrmt > > (loop)))))))))))) > > > > The problem is with the meta level vs. the expanded output level. You hav= e > two nested levels of #' . This (with-syntax ((CONTINUE ...)) ...) is part > of > the expanded output, it doesn't run when your macro is expanded. The body > of > the (expanded) loop just returns a syntax object. That's not what you wan= t. > Here's a definition that works: > > (define-syntax for/bc > (lambda (stx) > (syntax-case stx () > ((kwd (init test incrmt) body ...) > (with-syntax ((BREAK (datum->syntax #'kwd 'break)) > (CONTINUE (datum->syntax #'kwd 'continue))) > #'(call/cc > (lambda (escape) > (let-syntax ((BREAK (identifier-syntax (escape)))) > init > (let loop () > (when test > (call/cc > (lambda (next) > (let-syntax ((CONTINUE (identifier-syntax (next))= )) > body ...))) > incrmt > (loop))))))))))) > > (let ((i #f)) > (for/bc ((set! i 0) (< i 10) (set! i (1+ i))) > (when (< i 5) > continue) > (when (> i 9) > break) > (display i) > (newline))) > > > > You could also use quasisyntax (#` and #,) to get the same effect: > > > (define-syntax for/bc > (lambda (stx) > (syntax-case stx () > ((kwd (init test incrmt) body ...) > #`(call/cc > (lambda (escape) > (let-syntax ((#,(datum->syntax #'kwd 'break) > (identifier-syntax (escape)))) > init > (let loop () > (when test > (call/cc > (lambda (next) > (let-syntax ((#,(datum->syntax #'kwd 'continue) > (identifier-syntax (next)))) > body ...))) > incrmt > (loop)))))))))) > > > > That said, I would recommend using syntax parameters for break and > continue. > They're cleaner, since they can be rebound by the user. Also, you can > use let/ec from (ice-9 control) instead of call/cc. It's more efficient > because it doesn't need to actually reify the whole environment, since > an escape continuation is upwards-only (it can be used inside the > expression > to escape it, but it can't be used outside to reinstate its context). > > > (use-modules (ice-9 control)) > > (define-syntax-parameter break > (lambda (sintax) > (syntax-violation 'break "break outside of for/bc" sintax))) > > (define-syntax-parameter continue > (lambda (sintax) > (syntax-violation 'continue "continue outside of for/bc" sintax))) > > (define-syntax-rule (for/bc (init test increment) body body* ...) > (begin > init > (let/ec escape > (syntax-parameterize ((break (identifier-syntax (escape)))) > (let loop () > (when test > (let/ec next > (syntax-parameterize ((continue (identifier-syntax (next))= )) > body body* ...)) > increment > (loop))))))) > > (let ((i #f)) > (for/bc ((set! i 0) (< i 10) (set! i (1+ i))) > (when (< i 5) > continue) > (when (> i 9) > break) > (display i) > (newline))) > > > > > And here's an example showing the benefits of syntax parameters. > Add at the beginning of the code above: > > > (define-module (for) > #:export (break continue for/bc)) > > > In the same directory, put a file rename.scm containing: > > (use-modules ((for) > #:select ((break . for-break) continue for/bc)) > (srfi srfi-1) ; contains a break procedure > (ice-9 receive)) > > (let ((i #f)) > (for/bc ((set! i 0) (< i 10) (set! i (1+ i))) > (receive (before after) > (break (lambda (x) > (> x 5)) > (iota i)) > (when (pair? after) > for-break) > (display i)))) > > > > And run as > > guile -L . rename.scm > > As you can see, syntax parameters enable the code to use 'break' > for something else. > > A final note: are you aware of the existence of 'do' in Scheme? > Most cases of a C for loop can be written elegantly using do. > > https://www.gnu.org/software/guile/manual/html_node/while-do.html > > Regards, > Jean > >