* for with break and continue
@ 2022-09-04 9:54 Damien Mattei
2022-09-04 10:43 ` Jean Abou Samra
0 siblings, 1 reply; 7+ messages in thread
From: Damien Mattei @ 2022-09-04 9:54 UTC (permalink / raw)
To: guile-user
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))))))))))))
Damien
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: for with break and continue
2022-09-04 9:54 for with break and continue Damien Mattei
@ 2022-09-04 10:43 ` Jean Abou Samra
2022-09-04 12:00 ` Damien Mattei
0 siblings, 1 reply; 7+ messages in thread
From: Jean Abou Samra @ 2022-09-04 10:43 UTC (permalink / raw)
To: Damien Mattei, guile-user
Le 04/09/2022 à 11:54, Damien Mattei a écrit :
> 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 have
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 want.
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
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: for with break and continue
2022-09-04 10:43 ` Jean Abou Samra
@ 2022-09-04 12:00 ` Damien Mattei
2022-09-04 12:40 ` Jean Abou Samra
0 siblings, 1 reply; 7+ messages in thread
From: Damien Mattei @ 2022-09-04 12:00 UTC (permalink / raw)
To: Jean Abou Samra; +Cc: guile-user
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 <jean@abou-samra.fr> wrote:
> Le 04/09/2022 à 11:54, Damien Mattei a écrit :
> > 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 have
> 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 want.
> 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
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: for with break and continue
2022-09-04 12:00 ` Damien Mattei
@ 2022-09-04 12:40 ` Jean Abou Samra
2022-09-04 14:41 ` Damien Mattei
0 siblings, 1 reply; 7+ messages in thread
From: Jean Abou Samra @ 2022-09-04 12:40 UTC (permalink / raw)
To: Damien Mattei; +Cc: guile-user
Le 04/09/2022 à 14:00, Damien Mattei a écrit :
> yes very good
> then break si not overwritten, using module, i do not know if modules
> is finally standardised in R6RS, and in guile?
Guile supports R6RS libraries, but it's not the same as its traditional
use-modules/define-module forms.
https://www.gnu.org/software/guile/manual/html_node/R6RS-Libraries.html
But you're going to have a much more pressing problem with
standardization: syntax parameters are not standard. So you're a bit
stuck there.
> a few problem with module i hope to fix it later but it works with
> your example, not sure let/ec is standart?
let/ec is not standard, but exceptions are. See section 7 of the
libraries document of R6RS:
http://www.r6rs.org/final/r6rs-lib.pdf
Best,
Jean
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: for with break and continue
2022-09-04 12:40 ` Jean Abou Samra
@ 2022-09-04 14:41 ` Damien Mattei
2022-09-05 0:42 ` Jean Abou Samra
0 siblings, 1 reply; 7+ messages in thread
From: Damien Mattei @ 2022-09-04 14:41 UTC (permalink / raw)
To: Jean Abou Samra; +Cc: guile-user
yes in fact a lot of function related to syntax (datum->syntax, etc) are
not in R6RS and R7RS-small,
i have to keep that in mind because i want to write a library that could be
portable between scheme implementation and that support curly-infix ,less
than a number of scheme that count with the fingers of an hand ,at the
end.... :-) but 'for was a disgression,i know 'while of guile, again not
standard...
Regards,
Damien
On Sun, Sep 4, 2022 at 2:40 PM Jean Abou Samra <jean@abou-samra.fr> wrote:
>
>
> Le 04/09/2022 à 14:00, Damien Mattei a écrit :
> > yes very good
> > then break si not overwritten, using module, i do not know if modules
> > is finally standardised in R6RS, and in guile?
>
>
>
> Guile supports R6RS libraries, but it's not the same as its traditional
> use-modules/define-module forms.
>
> https://www.gnu.org/software/guile/manual/html_node/R6RS-Libraries.html
>
> But you're going to have a much more pressing problem with
> standardization: syntax parameters are not standard. So you're a bit
> stuck there.
>
>
>
> > a few problem with module i hope to fix it later but it works with
> > your example, not sure let/ec is standart?
>
>
> let/ec is not standard, but exceptions are. See section 7 of the
> libraries document of R6RS:
>
> http://www.r6rs.org/final/r6rs-lib.pdf
>
> Best,
> Jean
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: for with break and continue
2022-09-04 14:41 ` Damien Mattei
@ 2022-09-05 0:42 ` Jean Abou Samra
2022-09-05 8:46 ` Damien Mattei
0 siblings, 1 reply; 7+ messages in thread
From: Jean Abou Samra @ 2022-09-05 0:42 UTC (permalink / raw)
To: Damien Mattei; +Cc: guile-user
Le 04/09/2022 à 16:41, Damien Mattei a écrit :
> yes in fact a lot of function related to syntax (datum->syntax, etc)
> are not in R6RS and R7RS-small,
datum->syntax actually *is* R6RS, in the "libraries" document. See
http://www.r6rs.org/final/r6rs-lib.pdf page 55.
(It is not in R7RS small, since R7RS small doesn't even have syntax-case.)
> i have to keep that in mind because i want to write a library that
> could be portable between scheme implementation and that support
> curly-infix ,less than a number of scheme that count with the fingers
> of an hand ,at the end.... :-) but 'for was a disgression,i know
> 'while of guile, again not standard...
>
> Regards,
> Damien
>
> On Sun, Sep 4, 2022 at 2:40 PM Jean Abou Samra <jean@abou-samra.fr> wrote:
>
>
>
> Le 04/09/2022 à 14:00, Damien Mattei a écrit :
> > yes very good
> > then break si not overwritten, using module, i do not know if
> modules
> > is finally standardised in R6RS, and in guile?
>
>
>
> Guile supports R6RS libraries, but it's not the same as its
> traditional
> use-modules/define-module forms.
>
> https://www.gnu.org/software/guile/manual/html_node/R6RS-Libraries.html
>
> But you're going to have a much more pressing problem with
> standardization: syntax parameters are not standard. So you're a bit
> stuck there.
>
>
>
> > a few problem with module i hope to fix it later but it works with
> > your example, not sure let/ec is standart?
>
>
> let/ec is not standard, but exceptions are. See section 7 of the
> libraries document of R6RS:
>
> http://www.r6rs.org/final/r6rs-lib.pdf
>
> Best,
> Jean
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: for with break and continue
2022-09-05 0:42 ` Jean Abou Samra
@ 2022-09-05 8:46 ` Damien Mattei
0 siblings, 0 replies; 7+ messages in thread
From: Damien Mattei @ 2022-09-05 8:46 UTC (permalink / raw)
To: Jean Abou Samra; +Cc: guile-user
very interesting.
Finally is our functions,at least one, for/bc compatible with R6RS? i can
not exactly figure it exactly, i see at leats identifier-syntax not in the
library index:
http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-21.html#node_index_start
one day i will have to read the Dybvig article to understand all
that.Perhaps in a near future. ;-)
Damien
On Mon, Sep 5, 2022 at 2:42 AM Jean Abou Samra <jean@abou-samra.fr> wrote:
>
>
> Le 04/09/2022 à 16:41, Damien Mattei a écrit :
> > yes in fact a lot of function related to syntax (datum->syntax, etc)
> > are not in R6RS and R7RS-small,
>
>
> datum->syntax actually *is* R6RS, in the "libraries" document. See
> http://www.r6rs.org/final/r6rs-lib.pdf page 55.
>
> (It is not in R7RS small, since R7RS small doesn't even have syntax-case.)
>
>
> > i have to keep that in mind because i want to write a library that
> > could be portable between scheme implementation and that support
> > curly-infix ,less than a number of scheme that count with the fingers
> > of an hand ,at the end.... :-) but 'for was a disgression,i know
> > 'while of guile, again not standard...
> >
> > Regards,
> > Damien
> >
> > On Sun, Sep 4, 2022 at 2:40 PM Jean Abou Samra <jean@abou-samra.fr>
> wrote:
> >
> >
> >
> > Le 04/09/2022 à 14:00, Damien Mattei a écrit :
> > > yes very good
> > > then break si not overwritten, using module, i do not know if
> > modules
> > > is finally standardised in R6RS, and in guile?
> >
> >
> >
> > Guile supports R6RS libraries, but it's not the same as its
> > traditional
> > use-modules/define-module forms.
> >
> >
> https://www.gnu.org/software/guile/manual/html_node/R6RS-Libraries.html
> >
> > But you're going to have a much more pressing problem with
> > standardization: syntax parameters are not standard. So you're a bit
> > stuck there.
> >
> >
> >
> > > a few problem with module i hope to fix it later but it works with
> > > your example, not sure let/ec is standart?
> >
> >
> > let/ec is not standard, but exceptions are. See section 7 of the
> > libraries document of R6RS:
> >
> > http://www.r6rs.org/final/r6rs-lib.pdf
> >
> > Best,
> > Jean
> >
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-09-05 8:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-04 9:54 for with break and continue Damien Mattei
2022-09-04 10:43 ` Jean Abou Samra
2022-09-04 12:00 ` Damien Mattei
2022-09-04 12:40 ` Jean Abou Samra
2022-09-04 14:41 ` Damien Mattei
2022-09-05 0:42 ` Jean Abou Samra
2022-09-05 8:46 ` Damien Mattei
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).