* 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).