* Enhancement to the syntax system? @ 2012-06-30 15:22 Stefan Israelsson Tampe 2012-07-02 19:28 ` Ludovic Courtès 0 siblings, 1 reply; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-06-30 15:22 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 1925 bytes --] Hi, I want to discuss some of my experiences using the current syntax system when making the racket match matcher utilizing syntax-parse. When doing this I tried to use another style of macro parsing then seen in guiles ice-9 match e.g. Alex Shinns matcher for example. What I mean here is that I tried to use #' #, #,@ and calling out to functions in stead of writing one more macro. This works but it has a caveat. Hygiene is harder to maintain. e.g. I kept on hitting this kind of code snippets #'(let ((x v)) #,(f rest #'x)) The problem with this code is hygiene, I need to make a gensym and use with-syntax to bound x to that gensym in order to be safe at the macro expansion. Apart from this I liked the flow of the program and how natural it was to comprehend the code. The downside to this style is that we looses safety with respect to hygiene bugs. So can we improve on this. I would say yes! Consider introduceing #. and #.@ that works very much like #, and #,@ but with the distinction that #. creates a syntactic lambda e.g. The construction of the syntax object translates to #'(let ((x v)) #.(f rest #'x)) => #'(let ((x v)) #,(lambda (env) (with-syntax-env env (f rest #'x))) E.g. we inject a lambda inside the syntax structure to be parsed by the syntax expander later on and the syntax expander will recognize the lambda and call it with the current environment of the expander. The lambda will in turn set the syntax env that should be used by the #'x form in order match that x with the bounded x. I think that you get my intention. The question is why something like this does not exists. Is it because of weaknesses making this procedure unsound or any other reasons. I do think such a feature would be important but on the other hand, someone should have thought about this before and rejected the idea so my question is simply why is this rejected any clues or pointers? /Regards Stefan [-- Attachment #2: Type: text/html, Size: 2091 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-06-30 15:22 Enhancement to the syntax system? Stefan Israelsson Tampe @ 2012-07-02 19:28 ` Ludovic Courtès 2012-07-02 20:43 ` Stefan Israelsson Tampe 0 siblings, 1 reply; 24+ messages in thread From: Ludovic Courtès @ 2012-07-02 19:28 UTC (permalink / raw) To: guile-devel Hi Stefan, Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > Hygiene is harder to maintain. e.g. I kept on hitting this kind of code > snippets > > #'(let ((x v)) > #,(f rest #'x)) > > The problem with this code is hygiene, I need to make a gensym and use > with-syntax to bound x to that gensym in order to be safe > at the macro expansion. What do you mean? Here ‘x’ leads to a newly introduced binding. Likewise, the code below doesn’t introduce bindings non-hygienic bindings, and is non-ambiguous: (macroexpand '(let-syntax ((f (lambda (s) (syntax-case s () ((_ x y) #`(let ((p x)) (+ p #,(identity #'y)))))))) (f 1 2))) => #<tree-il (let (p) (p-28239) ((const 1)) (apply (toplevel +) (lexical p p-28239) (const 2)))> Thanks, Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-02 19:28 ` Ludovic Courtès @ 2012-07-02 20:43 ` Stefan Israelsson Tampe 2012-07-02 22:41 ` Ludovic Courtès 0 siblings, 1 reply; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-02 20:43 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel [-- Attachment #1: Type: text/plain, Size: 1392 bytes --] Maybe this help to see what I'm after, #'(let ((x v)) #.(f #'x)) <=> (let-syntax ((g (lambda (stx) (syntax-case stx ((_ x) (f #'x))))) #'(let ((x v)) (g x)) Now I would like to have a corresponding #.@ notation as well but can't find an analog for that :-( /Stefan On Mon, Jul 2, 2012 at 9:28 PM, Ludovic Courtès <ludo@gnu.org> wrote: > Hi Stefan, > > Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > > > Hygiene is harder to maintain. e.g. I kept on hitting this kind of code > > snippets > > > > #'(let ((x v)) > > #,(f rest #'x)) > > > > The problem with this code is hygiene, I need to make a gensym and use > > with-syntax to bound x to that gensym in order to be safe > > at the macro expansion. > > What do you mean? Here ‘x’ leads to a newly introduced binding. > > Likewise, the code below doesn’t introduce bindings non-hygienic > bindings, and is non-ambiguous: > > (macroexpand '(let-syntax ((f (lambda (s) > (syntax-case s () > ((_ x y) > #`(let ((p x)) > (+ p #,(identity #'y)))))))) > (f 1 2))) > > => #<tree-il (let (p) (p-28239) ((const 1)) (apply (toplevel +) (lexical > p p-28239) (const 2)))> > > Thanks, > Ludo’. > > > [-- Attachment #2: Type: text/html, Size: 1878 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-02 20:43 ` Stefan Israelsson Tampe @ 2012-07-02 22:41 ` Ludovic Courtès 2012-07-03 14:37 ` Stefan Israelsson Tampe 0 siblings, 1 reply; 24+ messages in thread From: Ludovic Courtès @ 2012-07-02 22:41 UTC (permalink / raw) To: Stefan Israelsson Tampe; +Cc: guile-devel Hey! Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > Maybe this help to see what I'm after, > > #'(let ((x v)) #.(f #'x)) > > <=> > > (let-syntax ((g (lambda (stx) (syntax-case stx ((_ x) (f #'x))))) > #'(let ((x v)) (g x)) Sorry, I fail to understand the problem you’re trying to solve. The above idiom is not frequent to the point that special syntax is needed, is it? Thanks, Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-02 22:41 ` Ludovic Courtès @ 2012-07-03 14:37 ` Stefan Israelsson Tampe 2012-07-03 21:33 ` Ludovic Courtès 0 siblings, 1 reply; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-03 14:37 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel [-- Attachment #1: Type: text/plain, Size: 1402 bytes --] On Tue, Jul 3, 2012 at 12:41 AM, Ludovic Courtès <ludo@gnu.org> wrote: > Hey! > > Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > > > Maybe this help to see what I'm after, > > > > #'(let ((x v)) #.(f #'x)) > > > > <=> > > > > (let-syntax ((g (lambda (stx) (syntax-case stx ((_ x) (f #'x))))) > > #'(let ((x v)) (g x)) > > Sorry, I fail to understand the problem you’re trying to solve. > > Hmm The #' probably need to be moved to the left of the expression and there might be problems with phases in this analogy but I guess you saw that I wanted to spin the function f on a syntax argument that contained the binding of x done in the let which is not the case If you do a simple #, The above idiom is not frequent to the point that special syntax is > needed, is it? > > If you want to code your macros like Alex does in ice-9/match.scm then it's not a problem. If you want to try another path using functions in stead of macros and working hard with #, and #,@ you will for complex macros like a matcher need to gensym by hand or destroy the readability of the code. As illustrated by the simple example above. It's not that a devastating issue because I have coded quite a lot of CL macros before and can cope with gensymming, but I find it frustrating to know that there probably exists a better way. > Thanks, > Ludo’. > /Stefan [-- Attachment #2: Type: text/html, Size: 2168 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-03 14:37 ` Stefan Israelsson Tampe @ 2012-07-03 21:33 ` Ludovic Courtès 2012-07-03 21:52 ` Stefan Israelsson Tampe 0 siblings, 1 reply; 24+ messages in thread From: Ludovic Courtès @ 2012-07-03 21:33 UTC (permalink / raw) To: Stefan Israelsson Tampe; +Cc: guile-devel Hey! Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: >> Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: >> >> > Maybe this help to see what I'm after, >> > >> > #'(let ((x v)) #.(f #'x)) >> > >> > <=> >> > >> > (let-syntax ((g (lambda (stx) (syntax-case stx ((_ x) (f #'x))))) >> > #'(let ((x v)) (g x)) [...] > If you want to try another path using functions in stead of macros and > working hard with #, and #,@ > you will for complex macros like a matcher need to gensym by hand or > destroy the readability of the > code. As illustrated by the simple example above. Hmm, the example above does not use gensym. What am I missing? Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-03 21:33 ` Ludovic Courtès @ 2012-07-03 21:52 ` Stefan Israelsson Tampe 2012-07-04 7:47 ` Marijn 2012-07-09 15:52 ` Ludovic Courtès 0 siblings, 2 replies; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-03 21:52 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel [-- Attachment #1: Type: text/plain, Size: 1291 bytes --] You do not need gensyms if you try to mimic or implement my suggested #. . On the other hand when if you do this (define (f stx) #`(let ((x 1)) #,stx)) and use this with #`(let ((x 2)) #,(f #'x)) the resulting expanded code would produce 1 which is not what you want. So in the racket matcher I wrote I needed to do (with-syntax ((x (datum->syntax stx (gensym "x")))) #`(let ((x 2)) #,(f #'x)))))) Hope that this makes things clear! /Stefan On Tue, Jul 3, 2012 at 11:33 PM, Ludovic Courtès <ludo@gnu.org> wrote: > Hey! > > Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > > >> Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > >> > >> > Maybe this help to see what I'm after, > >> > > >> > #'(let ((x v)) #.(f #'x)) > >> > > >> > <=> > >> > > >> > (let-syntax ((g (lambda (stx) (syntax-case stx ((_ x) (f #'x))))) > >> > #'(let ((x v)) (g x)) > > [...] > > > If you want to try another path using functions in stead of macros and > > working hard with #, and #,@ > > you will for complex macros like a matcher need to gensym by hand or > > destroy the readability of the > > code. As illustrated by the simple example above. > > Hmm, the example above does not use gensym. What am I missing? > > Ludo’. > [-- Attachment #2: Type: text/html, Size: 1910 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-03 21:52 ` Stefan Israelsson Tampe @ 2012-07-04 7:47 ` Marijn 2012-07-04 8:04 ` Stefan Israelsson Tampe 2012-07-09 15:52 ` Ludovic Courtès 1 sibling, 1 reply; 24+ messages in thread From: Marijn @ 2012-07-04 7:47 UTC (permalink / raw) To: Stefan Israelsson Tampe; +Cc: Ludovic Courtès, guile-devel -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Stefan, On 03-07-12 23:52, Stefan Israelsson Tampe wrote: > You do not need gensyms if you try to mimic or implement my > suggested #. . On the other hand when if you do this > > (define (f stx) #`(let ((x 1)) #,stx)) > > and use this with > > #`(let ((x 2)) #,(f #'x)) > > the resulting expanded code would produce 1 which is not what you > want. I tried it in Racket: (define-for-syntax (f stx) #`(let ((x 1)) #,stx)) (define-syntax (m stx) (syntax-case stx () ((_) #`(let ((x 2)) #,(f #'x))) )) (m) but I get error messages which I don't know what to do about. Do you have running examples of code not producing the result you want? Marijn -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk/z9PsACgkQp/VmCx0OL2xMNACbBJKq9nZJKTzCJbdnq0iPgJoE rSwAn2yJ1JTLMUn6v5ZR/PatxcGxgVrU =HFFX -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-04 7:47 ` Marijn @ 2012-07-04 8:04 ` Stefan Israelsson Tampe 0 siblings, 0 replies; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-04 8:04 UTC (permalink / raw) To: Marijn; +Cc: Ludovic Courtès, guile-devel [-- Attachment #1: Type: text/plain, Size: 1986 bytes --] Funny, for guile I get, scheme@(guile-user)> (define (f x) #`(let ((x 1)) #,x)) scheme@(guile-user)> (define-syntax m (lambda (x) (syntax-case x () ((_) #`(let ((x 2)) #,(f #'x)))))) scheme@(guile-user)> (m) $1 = 1 I ported the racket matcher to guile and worked in that environment, so this illustrate the problem. In racket the same idea will error out as you say (I did not find anything wrong with your example). I do prefer the racket behavior of bailing out because it can help detecting the bug in stead of silently behave against the intention for newbies. My original code where this issue comes from is located in compat/racket/match/match.scm in the syntax-parse repo at https://gitorious.org/guile-syntax-parse/guile-syntax-parse This is the racket matcher implemented using syntax-parse! These bugs should have been corrected though in that code! /Stefan On Wed, Jul 4, 2012 at 9:47 AM, Marijn <hkBst@gentoo.org> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hi Stefan, > > On 03-07-12 23:52, Stefan Israelsson Tampe wrote: > > You do not need gensyms if you try to mimic or implement my > > suggested #. . On the other hand when if you do this > > > > (define (f stx) #`(let ((x 1)) #,stx)) > > > > and use this with > > > > #`(let ((x 2)) #,(f #'x)) > > > > the resulting expanded code would produce 1 which is not what you > > want. > > I tried it in Racket: > > > (define-for-syntax (f stx) #`(let ((x 1)) #,stx)) > > (define-syntax (m stx) > (syntax-case stx () > ((_) #`(let ((x 2)) #,(f #'x))) )) > > (m) > > > but I get error messages which I don't know what to do about. Do you > have running examples of code not producing the result you want? > > Marijn > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v2.0.19 (GNU/Linux) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ > > iEYEARECAAYFAk/z9PsACgkQp/VmCx0OL2xMNACbBJKq9nZJKTzCJbdnq0iPgJoE > rSwAn2yJ1JTLMUn6v5ZR/PatxcGxgVrU > =HFFX > -----END PGP SIGNATURE----- > [-- Attachment #2: Type: text/html, Size: 2642 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-03 21:52 ` Stefan Israelsson Tampe 2012-07-04 7:47 ` Marijn @ 2012-07-09 15:52 ` Ludovic Courtès 2012-07-09 17:40 ` Stefan Israelsson Tampe 2012-07-10 7:36 ` Stefan Israelsson Tampe 1 sibling, 2 replies; 24+ messages in thread From: Ludovic Courtès @ 2012-07-09 15:52 UTC (permalink / raw) To: guile-devel Hi! Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > You do not need gensyms if you try to mimic or implement my suggested #. . > On the > other hand when if you do this > > (define (f stx) #`(let ((x 1)) #,stx)) > > and use this with > > #`(let ((x 2)) #,(f #'x)) OK, got it, thanks! (In case others wonder, the complete example is: (define (f stx) #`(let ((x 1)) #,stx)) (define-syntax foo (lambda (s) (syntax-case s () ((_) #`(let ((x 2)) #,(f #'x)))))) (foo) => 1 ) The situation can be diagnosed with: (define (f stx) #`(let ((x 1)) #,(if (bound-identifier=? stx #'x) (error) stx))) But it doesn’t help. > (with-syntax ((x (datum->syntax stx (gensym "x")))) #`(let ((x 2)) #,(f > #'x)))))) Often, you could use ‘generate-temporaries’, which is a bit nicer. > Hope that this makes things clear! It does, thanks! It’s true that it’s annoying that the wrong binding is silently used. Do you think it’s common enough to justify new syntax? Thanks, Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-09 15:52 ` Ludovic Courtès @ 2012-07-09 17:40 ` Stefan Israelsson Tampe 2012-07-10 8:24 ` Ludovic Courtès 2012-07-10 7:36 ` Stefan Israelsson Tampe 1 sibling, 1 reply; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-09 17:40 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel [-- Attachment #1: Type: text/plain, Size: 2169 bytes --] | It’s true that it’s annoying that the wrong binding is silently used. | Do you think it’s common enough to justify new syntax? Yes this highlights a comon problem when implementing racket match with #`. I do think that the best solution is to somehow extend the syntax expander to mimic my sugested #. and #.@. The simple solution is to rewrite according to #`(... #.((x y) (f #'x #'y))) -> #`(let-syntax ((g (lambda (x) (syntax-case x () ((_ x y) (f #'x #'y)))))) (... (g x y)) But before going this path it would be interesting to hear what the true wizards of scheme have to say about this. It might have been considered already and good advice could be taken from them. I also feel that the issue needs to be liffted up to the community of at least syntax-case user crowd before doing anything Ill try to spur some discussions on it and come back later! /Stefan On Mon, Jul 9, 2012 at 5:52 PM, Ludovic Courtès <ludo@gnu.org> wrote: > Hi! > > Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > > > You do not need gensyms if you try to mimic or implement my suggested #. > . > > On the > > other hand when if you do this > > > > (define (f stx) #`(let ((x 1)) #,stx)) > > > > and use this with > > > > #`(let ((x 2)) #,(f #'x)) > > OK, got it, thanks! > > (In case others wonder, the complete example is: > > (define (f stx) > #`(let ((x 1)) #,stx)) > (define-syntax foo > (lambda (s) > (syntax-case s () > ((_) > #`(let ((x 2)) #,(f #'x)))))) > > (foo) > => 1 > ) > > The situation can be diagnosed with: > > (define (f stx) > #`(let ((x 1)) > #,(if (bound-identifier=? stx #'x) (error) stx))) > > But it doesn’t help. > > > (with-syntax ((x (datum->syntax stx (gensym "x")))) #`(let ((x 2)) #,(f > > #'x)))))) > > Often, you could use ‘generate-temporaries’, which is a bit nicer. > > > Hope that this makes things clear! > > It does, thanks! > > It’s true that it’s annoying that the wrong binding is silently used. > Do you think it’s common enough to justify new syntax? > > Thanks, > Ludo’. > > > [-- Attachment #2: Type: text/html, Size: 2892 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-09 17:40 ` Stefan Israelsson Tampe @ 2012-07-10 8:24 ` Ludovic Courtès 2012-07-10 13:35 ` Stefan Israelsson Tampe 0 siblings, 1 reply; 24+ messages in thread From: Ludovic Courtès @ 2012-07-10 8:24 UTC (permalink / raw) To: Stefan Israelsson Tampe; +Cc: guile-devel Hi! Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > | It’s true that it’s annoying that the wrong binding is silently used. > | Do you think it’s common enough to justify new syntax? > > Yes this highlights a comon problem when implementing racket match with #`. Sure, but it’s not good-style. ;-) In general, ‘syntax-case’ is great, but it’s low-level plumbing to be used with care, compared to ‘syntax-rules’. > I do think > that the best solution is to somehow extend the syntax expander to mimic my > sugested > #. and #.@. The simple solution is to rewrite according to > > #`(... #.((x y) (f #'x #'y))) > > -> > > #`(let-syntax ((g (lambda (x) (syntax-case x () ((_ x y) (f #'x #'y)))))) > (... (g x y)) Unlike syntax-{quote,unquote,...}, #. has no non-syntax-prefixed equivalent. And what it does is non-trivial. So I don’t feel comfortable with this extension, FWIW. [...] > I also feel that the issue needs to be > liffted up to the > community of at least syntax-case user crowd before doing anything Ill try > to spur > some discussions on it and come back later! Yes, this should be discussed on c.l.s or scheme-reports. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-10 8:24 ` Ludovic Courtès @ 2012-07-10 13:35 ` Stefan Israelsson Tampe 2012-07-10 14:34 ` Marijn 2012-07-10 15:22 ` Ludovic Courtès 0 siblings, 2 replies; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-10 13:35 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel [-- Attachment #1: Type: text/plain, Size: 1952 bytes --] I did miss something when trying in racket, it's a psyntax bug! Look! racket: (define-for-syntax (f x) #`(let ((x 1)) #,x)) > (define-syntax (g x) (syntax-case x ()((_ y) #`(let ((x y)) #,(f #'x)))) ) > (g 4) 4 In guile, scheme@(guile-user)> (define (f x) #`(let ((x 1)) #,x)) scheme@(guile-user)> (define-syntax g (lambda (x) (syntax-case x () ((_ y) #`(let ((x y)) #,(f #'x)))))) scheme@(guile-user)> (g 4) $1 = 1 ! I much prefer rackets version here. I will file a bug report and also try to understand what spec that racket is following! On Tue, Jul 10, 2012 at 10:24 AM, Ludovic Courtès <ludo@gnu.org> wrote: > Hi! > > Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > > > | It’s true that it’s annoying that the wrong binding is silently used. > > | Do you think it’s common enough to justify new syntax? > > > > Yes this highlights a comon problem when implementing racket match with > #`. > > Sure, but it’s not good-style. ;-) In general, ‘syntax-case’ is great, > but it’s low-level plumbing to be used with care, compared to > ‘syntax-rules’. > > > I do think > > that the best solution is to somehow extend the syntax expander to mimic > my > > sugested > > #. and #.@. The simple solution is to rewrite according to > > > > #`(... #.((x y) (f #'x #'y))) > > > > -> > > > > #`(let-syntax ((g (lambda (x) (syntax-case x () ((_ x y) (f #'x #'y)))))) > > (... (g x y)) > > Unlike syntax-{quote,unquote,...}, #. has no non-syntax-prefixed > equivalent. And what it does is non-trivial. So I don’t feel > comfortable with this extension, FWIW. > > [...] > > > I also feel that the issue needs to be > > liffted up to the > > community of at least syntax-case user crowd before doing anything Ill > try > > to spur > > some discussions on it and come back later! > > Yes, this should be discussed on c.l.s or scheme-reports. > > Thanks, > Ludo’. > [-- Attachment #2: Type: text/html, Size: 2531 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-10 13:35 ` Stefan Israelsson Tampe @ 2012-07-10 14:34 ` Marijn 2012-07-10 14:51 ` [racket-dev] " Eli Barzilay 2012-07-10 15:22 ` Ludovic Courtès 1 sibling, 1 reply; 24+ messages in thread From: Marijn @ 2012-07-10 14:34 UTC (permalink / raw) To: Stefan Israelsson Tampe, dev@racket-lang.org Cc: Ludovic Courtès, guile-devel -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 10-07-12 15:35, Stefan Israelsson Tampe wrote: > I did miss something when trying in racket, it's a psyntax bug! I'm glad you're finally looking harder at the Racket behavior. > racket: (define-for-syntax (f x) #`(let ((x 1)) #,x)) >> (define-syntax (g x) (syntax-case x ()((_ y) #`(let ((x y)) #,(f >> #'x)))) > ) >> (g 4) > 4 This code produces the same error for me with Racket which I reported earlier, but I seem to have been using a non-release version. So, switching to 5.2.1, I can report that indeed the code #lang racket (define-for-syntax (f x) #`(let ((x 1)) #,x)) (define-syntax (g x) (syntax-case x () ((_ y) #`(let ((x y)) #,(f #'x))))) (g 4) produces 4, which makes sense to me. However when I retry my earlier example #lang racket (define-for-syntax (f stx) #`(let ((x 1)) #,stx)) (define-syntax (m stx) (syntax-case stx () ((_) #`(let ((x 2)) #,(f #'x))) )) (m) it now produces 1 instead of the expected 2. It seems to me that both these results cannot be correct simultaneously, but I'll await the experts' opinion on that. Marijn -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk/8PXIACgkQp/VmCx0OL2zdfQCeOVJz/ECKExThGPJoqvRY3E41 gr0An0vSsuXK2B7xi0WT0LuzvVvhUbcy =04xS -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [racket-dev] Enhancement to the syntax system? 2012-07-10 14:34 ` Marijn @ 2012-07-10 14:51 ` Eli Barzilay [not found] ` <20476.16781.257276.194149-a5nvgYPMCZcx/1z6v04GWfZ8FUJU4vz8@public.gmane.org> 0 siblings, 1 reply; 24+ messages in thread From: Eli Barzilay @ 2012-07-10 14:51 UTC (permalink / raw) To: Marijn; +Cc: Ludovic Courtès, guile-devel, dev@racket-lang.org 20 minutes ago, Marijn wrote: > > It seems to me that both these results cannot be correct > simultaneously, but I'll await the experts' opinion on that. This does look weird: #lang racket (define-for-syntax (f stx) #`(let ([x 1]) #,stx)) (define-syntax (m stx) (with-syntax ([zz (f #'x)]) #`(let ([x 2]) zz))) (m) evaluates to 1, but if I change the first two "stx" names into "x" *or* if I change the argument name for the macro to "x", then it returns 2. -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! ^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <20476.16781.257276.194149-a5nvgYPMCZcx/1z6v04GWfZ8FUJU4vz8@public.gmane.org>]
* Re: Enhancement to the syntax system? [not found] ` <20476.16781.257276.194149-a5nvgYPMCZcx/1z6v04GWfZ8FUJU4vz8@public.gmane.org> @ 2012-07-10 15:03 ` Matthew Flatt 2012-07-10 15:26 ` [racket-dev] " Ludovic Courtès ` (2 more replies) 2012-07-10 15:44 ` Ryan Culpepper 1 sibling, 3 replies; 24+ messages in thread From: Matthew Flatt @ 2012-07-10 15:03 UTC (permalink / raw) To: Eli Barzilay Cc: dev-GvBox1K3Ixw1Q5oZIJT9Xw@public.gmane.org, Ludovic Courtès, guile-devel-mXXj517/zsQ At Tue, 10 Jul 2012 10:51:57 -0400, Eli Barzilay wrote: > 20 minutes ago, Marijn wrote: > > > > It seems to me that both these results cannot be correct > > simultaneously, but I'll await the experts' opinion on that. > > This does look weird: > > #lang racket > (define-for-syntax (f stx) #`(let ([x 1]) #,stx)) > (define-syntax (m stx) > (with-syntax ([zz (f #'x)]) #`(let ([x 2]) zz))) > (m) > > evaluates to 1, but if I change the first two "stx" names into "x" > *or* if I change the argument name for the macro to "x", then it > returns 2. It's natural --- but not correct --- to think that #` is responsible for hygiene, in which case `(f #'x)' should keep the given `x' separate from the `let'-bound `x' in the result. Instead, hygiene is the responsibility of macro invocation, and #`(let ([x 1]) #,#'x) is simply the same as #`(let ([x 1]) x) and so (f #'x) above is equivalent to #`(let ([x 1]) x) If you change the example to #lang racket (begin-for-syntax (define-syntax-rule (f body) #`(let ([x 1]) body))) (define-syntax (m stx) (with-syntax ([zz (f x)]) #`(let ([x 2]) zz))) (m) so that `f' is used as a macro instead of a function, then you get 2, since the macro-expansion of `(f x)' keeps the `x's separate. _________________________ Racket Developers list: http://lists.racket-lang.org/dev ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [racket-dev] Enhancement to the syntax system? 2012-07-10 15:03 ` Matthew Flatt @ 2012-07-10 15:26 ` Ludovic Courtès 2012-07-10 15:44 ` Stefan Israelsson Tampe 2012-07-10 16:48 ` Eli Barzilay 2014-05-03 21:29 ` Marijn Schouten (hkBst) 2 siblings, 1 reply; 24+ messages in thread From: Ludovic Courtès @ 2012-07-10 15:26 UTC (permalink / raw) To: Matthew Flatt; +Cc: dev@racket-lang.org, Eli Barzilay, guile-devel Hi, Matthew Flatt <mflatt@cs.utah.edu> skribis: > It's natural --- but not correct --- to think that #` is responsible > for hygiene, in which case `(f #'x)' should keep the given `x' separate > from the `let'-bound `x' in the result. [...] > If you change the example to > > #lang racket > (begin-for-syntax > (define-syntax-rule (f body) > #`(let ([x 1]) body))) > (define-syntax (m stx) > (with-syntax ([zz (f x)]) #`(let ([x 2]) zz))) > (m) > > so that `f' is used as a macro instead of a function, then you get 2, > since the macro-expansion of `(f x)' keeps the `x's separate. Interesting. Thanks for the clarification and examples. Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [racket-dev] Enhancement to the syntax system? 2012-07-10 15:26 ` [racket-dev] " Ludovic Courtès @ 2012-07-10 15:44 ` Stefan Israelsson Tampe 2012-07-10 17:47 ` Stefan Israelsson Tampe 0 siblings, 1 reply; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-10 15:44 UTC (permalink / raw) To: Ludovic Courtès Cc: Matthew Flatt, dev@racket-lang.org, Eli Barzilay, guile-devel [-- Attachment #1: Type: text/plain, Size: 1016 bytes --] samth made a pointer to http://srfi.schemers.org/srfi-72/srfi-72.html It does not look like guile racket etc. have implemented this yet. Am I wrong? This is precisely what I'm after! On Tue, Jul 10, 2012 at 5:26 PM, Ludovic Courtès <ludo@gnu.org> wrote: > Hi, > > Matthew Flatt <mflatt@cs.utah.edu> skribis: > > > It's natural --- but not correct --- to think that #` is responsible > > for hygiene, in which case `(f #'x)' should keep the given `x' separate > > from the `let'-bound `x' in the result. > > [...] > > > If you change the example to > > > > #lang racket > > (begin-for-syntax > > (define-syntax-rule (f body) > > #`(let ([x 1]) body))) > > (define-syntax (m stx) > > (with-syntax ([zz (f x)]) #`(let ([x 2]) zz))) > > (m) > > > > so that `f' is used as a macro instead of a function, then you get 2, > > since the macro-expansion of `(f x)' keeps the `x's separate. > > Interesting. Thanks for the clarification and examples. > > Ludo’. > > [-- Attachment #2: Type: text/html, Size: 1565 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [racket-dev] Enhancement to the syntax system? 2012-07-10 15:44 ` Stefan Israelsson Tampe @ 2012-07-10 17:47 ` Stefan Israelsson Tampe 0 siblings, 0 replies; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-10 17:47 UTC (permalink / raw) To: dev, guile-devel [-- Attachment #1: Type: text/plain, Size: 3505 bytes --] The question I posed was If it's possible to use srfi-72 in guile or racket. It is indeed a wish of mine that it's implemented because it will most certainly help me write beutiful code because that srfi cater to the coding style Ichoose to have. Without it one most certainly need to use with-syntax to introduce the bindings in order to be safe and avoid a multiple of possible syntactic loopholes as can see if you read André van Tonder's http://srfi.schemers.org/srfi-72/srfi-72.html Anyway one does not need to change psyntax in order to come close to that system. A more hacky way is to use code like the one at the end of this document. It's a reiteration and improvement on a previous version. So with this hack I can write, ------------- (use-modules (syntax unquote++)) (define (f x y) #`(let ((x 1)) (+ #,x #,y))) (define (h y) ##`(let ((x 2)) #.((x) (f x y)))) (define-syntax g (lambda (x) (syntax-case x () ((_ y) ##`(let ((x y)) #.((x) (h x))))))) scheme@(guile-user)> (g 3) $2 = 5 -------------- In racket, (define-for-syntax (f x y) #`(let ((x 1)) (+ #,x #,y))) (define-for-syntax (h y) #`(let ((x 2)) #,(f #'x y)) (define-syntax (g stx) (syntax-case stx () ((_ y) #`(let ((x y)) #,(h #'x))))) > (g 3) 4 -------------- This shows that it was just luck previously when racket produced the correct (for my intention) answer. with srfi-72 a correct answer would have been produced. Without srfi-72 I will then move over to use ##` and #. in my code because it will be easy to transfer later on if when srfi-72 is available in some form. /Stefan (define-module (syntax unquote++) #:export (quasisyntax++ insyntax)) (define *s* (make-fluid '())) (define *t* (make-fluid '())) (define table (make-weak-key-hash-table)) (define (add-lambda lam) (let* ((id (gensym "id")) (x (datum->syntax #'table id))) (hashq-set! table id lam) x)) (define (plexer x . l) (let ((lam (hashq-ref table x))) (apply lam l))) (define (parse stx x) (syntax-case x (unsyntax insyntax unsyntax-splicing) ((unsyntax . _) x) ((unsyntax-splicing . _) x) ((insyntax ((p ...) c ...)) (with-syntax ((g (datum->syntax stx (gensym "g"))) (i (datum->syntax stx (gensym "i")))) (fluid-set! *s* (cons #'(g (lambda (x) (syntax-case x () ((_ p ...) (plexer 'i #'p ...))))) (fluid-ref *s*))) (fluid-set! *t* (cons #'(i (add-lambda (lambda (p ...) (begin c ...)))) (fluid-ref *t*))) #'(g p ...))) ((x . l) (cons (parse stx #'x) (parse stx #'l))) (x #'x))) (define-syntax quasisyntax++ (lambda (x) (syntax-case x () ((_ y) (begin (fluid-set! *s* '()) (fluid-set! *t* '()) (with-syntax ((statement (parse x #'y)) (lets (fluid-ref *s*)) (withs (fluid-ref *t*))) #'(with-syntax withs #`(let-syntax lets statement)))))))) (define (rg ch stream) (let ((x (read-char stream))) (cond ((eqv? x #\`) `(quasisyntax++ ,(read stream))) (#t (error "Wrong format of # reader extension"))))) (define (rg. ch stream) `(insyntax ,(read stream))) (read-hash-extend #\# rg) (read-hash-extend #\. rg.) [-- Attachment #2: Type: text/html, Size: 3933 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [racket-dev] Enhancement to the syntax system? 2012-07-10 15:03 ` Matthew Flatt 2012-07-10 15:26 ` [racket-dev] " Ludovic Courtès @ 2012-07-10 16:48 ` Eli Barzilay 2014-05-03 21:29 ` Marijn Schouten (hkBst) 2 siblings, 0 replies; 24+ messages in thread From: Eli Barzilay @ 2012-07-10 16:48 UTC (permalink / raw) To: Ryan Culpepper, Matthew Flatt Cc: dev@racket-lang.org, Ludovic Courtès, guile-devel An hour and a half ago, Matthew Flatt wrote: > > It's natural --- but not correct --- to think that #` is responsible > for hygiene, in which case `(f #'x)' should keep the given `x' > separate from the `let'-bound `x' in the result. > > Instead, hygiene is the responsibility of macro invocation, and > > #`(let ([x 1]) #,#'x) > > is simply the same as > > #`(let ([x 1]) x) > > and so > > (f #'x) > > above is equivalent to > > #`(let ([x 1]) x) > > > If you change the example to > > #lang racket > (begin-for-syntax > (define-syntax-rule (f body) > #`(let ([x 1]) body))) > (define-syntax (m stx) > (with-syntax ([zz (f x)]) #`(let ([x 2]) zz))) > (m) > > so that `f' is used as a macro instead of a function, then you get 2, > since the macro-expansion of `(f x)' keeps the `x's separate. Yeah, I think that this kind of confusion is there, but it's easy (at least "relatively easy") to build a mental model of how things work and avoid such problems -- but the tricky bit here is that things break when the `stx' is renamed to `x'. 50 minutes ago, Ryan Culpepper wrote: > > The difference between > > (define-for-syntax (f1 stx) #`(let ([x 1]) #,stx) > > and > > (define-for-syntax (f2 x) #`(let ([x 1]) #,x) > > is that the 'x' in the template in the 'f2' is not bound-identifier=? to > the 'x' that appears in the template of 'm', because it has a rename > wrap due to the 'x' formal parameter of 'f2'. That is, 'f2' behaves > essentially the same as > > (define-for-syntax (f2* x*) #`(let ([x* 1]) #,x*) Yeah, I think that this is the more confusing bit. (I suspected something along this line, but didn't have time to figure out a good explanation...) So I think that the real confusion is actually a combination of what Matthew pointed at in the above and this one, making the result trickier than both. In other words, I *think* that the effect of the transformer's argument name makes it looks like the #` *was* responsible for hygiene when it's actually just this point that makes it happen... (This is all "IIUC".) > A likely mistake is to think that the wrap generated by the 'x' in > 'f2' doesn't count because it happens before we get around to the > "real" macro expansion that you care about. But that's not the case > (at least in Racket). > > A good rule of thumb is to never use local variable names in your > macro implementation (including compile-time auxiliary functions) > that also appear in the macro's template (including etc). Yeah, and a subtle lesson here is that `stx' is a useful convention. (I think that `x' is common in some guile code, so this would be a point for them.) > A related error is the "identifier used out of context" error that > you get from, eg, > > (define-syntax (m stx) > (let ([+ *]) > #'(+ 1 2))) > (m) ;; => identifier used out of context in: + > > The binding of '+' in the macro changes the meaning of the '+' in > the template, even though the bindings exist at different > phases. You could perhaps avoid this issue by changing the hygiene > algorithm by adding a phase level to rename wraps and skipping > different-phase rename wraps during resolution. I'm not sure if this > is a good idea or if anyone has tried it. (And this is what Matthew's last example gets by changing `f' to a macro, right? Also, Stefan posted a related message to the scheme-reports list where he imlpemented some new #. thing which is (roughly speaking) something that expands to a `let-syntax' and therefore tries to do the same.) In any case, it would be nice if the original example I posted (which is a variant of what was discussed originally) would throw an error instead of looking right in a way that is wrong... -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [racket-dev] Enhancement to the syntax system? 2012-07-10 15:03 ` Matthew Flatt 2012-07-10 15:26 ` [racket-dev] " Ludovic Courtès 2012-07-10 16:48 ` Eli Barzilay @ 2014-05-03 21:29 ` Marijn Schouten (hkBst) 2 siblings, 0 replies; 24+ messages in thread From: Marijn Schouten (hkBst) @ 2014-05-03 21:29 UTC (permalink / raw) To: Matthew Flatt, Eli Barzilay Cc: dev@racket-lang.org, Ludovic Courtès, guile-devel On 07/10/2012 05:03 PM, Matthew Flatt wrote: > At Tue, 10 Jul 2012 10:51:57 -0400, Eli Barzilay wrote: >> 20 minutes ago, Marijn wrote: >>> >>> It seems to me that both these results cannot be correct >>> simultaneously, but I'll await the experts' opinion on that. >> >> This does look weird: >> >> #lang racket >> (define-for-syntax (f stx) #`(let ([x 1]) #,stx)) >> (define-syntax (m stx) >> (with-syntax ([zz (f #'x)]) #`(let ([x 2]) zz))) >> (m) >> >> evaluates to 1, but if I change the first two "stx" names into "x" >> *or* if I change the argument name for the macro to "x", then it >> returns 2. > > It's natural --- but not correct --- to think that #` is responsible > for hygiene, in which case `(f #'x)' should keep the given `x' separate > from the `let'-bound `x' in the result. > > Instead, hygiene is the responsibility of macro invocation, and > > #`(let ([x 1]) #,#'x) > > is simply the same as > > #`(let ([x 1]) x) > > and so > > (f #'x) > > above is equivalent to > > #`(let ([x 1]) x) IIUC then you're saying that also all the following (fx #'x) and (fy #'x) are equivalent to #`(let ((x 0)) x), but if you run this code then you will get a 0 result only for (myy), contrary to what I would expect based on the above explanation. #lang racket (define-for-syntax (fx x) #`(let ((x 0)) #,x)) (define-for-syntax (fy y) #`(let ((x 0)) #,y)) (define-syntax (mxx x) (syntax-case x () ((_) #`(let ((x 99)) #,(fx #'x))))) (define-syntax (mxy x) (syntax-case x () ((_) #`(let ((x 99)) #,(fy #'x))))) (define-syntax (myx y) (syntax-case y () ((_) #`(let ((x 99)) #,(fx #'x))))) (define-syntax (myy y) (syntax-case y () ((_) #`(let ((x 99)) #,(fy #'x))))) (mxx) (mxy) (myx) (myy) ==> 99 99 99 0 Marijn ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? [not found] ` <20476.16781.257276.194149-a5nvgYPMCZcx/1z6v04GWfZ8FUJU4vz8@public.gmane.org> 2012-07-10 15:03 ` Matthew Flatt @ 2012-07-10 15:44 ` Ryan Culpepper 1 sibling, 0 replies; 24+ messages in thread From: Ryan Culpepper @ 2012-07-10 15:44 UTC (permalink / raw) To: Eli Barzilay Cc: dev-GvBox1K3Ixw1Q5oZIJT9Xw@public.gmane.org, Ludovic Courtès, guile-devel-mXXj517/zsQ On 07/10/2012 10:51 AM, Eli Barzilay wrote: > 20 minutes ago, Marijn wrote: >> >> It seems to me that both these results cannot be correct >> simultaneously, but I'll await the experts' opinion on that. > > This does look weird: > > #lang racket > (define-for-syntax (f stx) #`(let ([x 1]) #,stx)) > (define-syntax (m stx) > (with-syntax ([zz (f #'x)]) #`(let ([x 2]) zz))) > (m) > > evaluates to 1, but if I change the first two "stx" names into "x" > *or* if I change the argument name for the macro to "x", then it > returns 2. The difference between (define-for-syntax (f1 stx) #`(let ([x 1]) #,stx) and (define-for-syntax (f2 x) #`(let ([x 1]) #,x) is that the 'x' in the template in the 'f2' is not bound-identifier=? to the 'x' that appears in the template of 'm', because it has a rename wrap due to the 'x' formal parameter of 'f2'. That is, 'f2' behaves essentially the same as (define-for-syntax (f2* x*) #`(let ([x* 1]) #,x*) A likely mistake is to think that the wrap generated by the 'x' in 'f2' doesn't count because it happens before we get around to the "real" macro expansion that you care about. But that's not the case (at least in Racket). A good rule of thumb is to never use local variable names in your macro implementation (including compile-time auxiliary functions) that also appear in the macro's template (including etc). A related error is the "identifier used out of context" error that you get from, eg, (define-syntax (m stx) (let ([+ *]) #'(+ 1 2))) (m) ;; => identifier used out of context in: + The binding of '+' in the macro changes the meaning of the '+' in the template, even though the bindings exist at different phases. You could perhaps avoid this issue by changing the hygiene algorithm by adding a phase level to rename wraps and skipping different-phase rename wraps during resolution. I'm not sure if this is a good idea or if anyone has tried it. Ryan _________________________ Racket Developers list: http://lists.racket-lang.org/dev ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-10 13:35 ` Stefan Israelsson Tampe 2012-07-10 14:34 ` Marijn @ 2012-07-10 15:22 ` Ludovic Courtès 1 sibling, 0 replies; 24+ messages in thread From: Ludovic Courtès @ 2012-07-10 15:22 UTC (permalink / raw) To: Stefan Israelsson Tampe; +Cc: guile-devel Hi, Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > racket: > (define-for-syntax (f x) #`(let ((x 1)) #,x)) >> (define-syntax (g x) (syntax-case x ()((_ y) #`(let ((x y)) #,(f #'x)))) > ) >> (g 4) > 4 > > In guile, > scheme@(guile-user)> (define (f x) #`(let ((x 1)) #,x)) > scheme@(guile-user)> (define-syntax g (lambda (x) (syntax-case x () ((_ y) > #`(let ((x y)) #,(f #'x)))))) > scheme@(guile-user)> (g 4) > $1 = 1 > ! > > I much prefer rackets version here. I will file a bug report and also try > to understand what spec that racket is following! Aaah, indeed, that’s a “better” outcome! :-) Ludo’. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Enhancement to the syntax system? 2012-07-09 15:52 ` Ludovic Courtès 2012-07-09 17:40 ` Stefan Israelsson Tampe @ 2012-07-10 7:36 ` Stefan Israelsson Tampe 1 sibling, 0 replies; 24+ messages in thread From: Stefan Israelsson Tampe @ 2012-07-10 7:36 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel [-- Attachment #1.1: Type: text/plain, Size: 2725 bytes --] Ok, I coded a suggested syntax that is a quick solution but maybe not ideal because really this should be hanlded on the psyntax level. We probably cannot use the old syntax because it can break old code in other words one has to introduce new language elements. Also I asked on #scheme and tried to look into reference documentation for quasisyntax semantics. The answer I got on #scheme was that psyntax is buggy although I do not agree on that. I also felt that people is suspicious of my approach which is to write one macro and then dispatch to functions in stead of writing macro after macro. In all I don't think I am able to lift this idea to a larger community. So I sat down and implemented a simple algorithm see attachement. with this I can write, scheme@(guile-user)> (use-modules (syntax unquote++)) scheme@(guile-user)> (define (f x) #`(let ((x 1)) #,x)) scheme@(guile-user)> (define-syntax g (lambda (x) (syntax-case x () ((_ y) ##`(let ((x y)) #.((x) (f #'x))))))) scheme@(guile-user)> (g 4) $1 = 4 This will explicitly state what variables to transfer to the inserted expression. It's not ideal because I feel that the good way to handle this is to implicitly, which demands hacking psyntax, do this and simplify the syntax even more. also I cannot see how to implement #.@ but to hack psyntax. ##` also allow #, and #,@ which has the old meaning. Have fun /Stefan On Mon, Jul 9, 2012 at 5:52 PM, Ludovic Courtès <ludo@gnu.org> wrote: > Hi! > > Stefan Israelsson Tampe <stefan.itampe@gmail.com> skribis: > > > You do not need gensyms if you try to mimic or implement my suggested #. > . > > On the > > other hand when if you do this > > > > (define (f stx) #`(let ((x 1)) #,stx)) > > > > and use this with > > > > #`(let ((x 2)) #,(f #'x)) > > OK, got it, thanks! > > (In case others wonder, the complete example is: > > (define (f stx) > #`(let ((x 1)) #,stx)) > (define-syntax foo > (lambda (s) > (syntax-case s () > ((_) > #`(let ((x 2)) #,(f #'x)))))) > > (foo) > => 1 > ) > > The situation can be diagnosed with: > > (define (f stx) > #`(let ((x 1)) > #,(if (bound-identifier=? stx #'x) (error) stx))) > > But it doesn’t help. > > > (with-syntax ((x (datum->syntax stx (gensym "x")))) #`(let ((x 2)) #,(f > > #'x)))))) > > Often, you could use ‘generate-temporaries’, which is a bit nicer. > > > Hope that this makes things clear! > > It does, thanks! > > It’s true that it’s annoying that the wrong binding is silently used. > Do you think it’s common enough to justify new syntax? > > Thanks, > Ludo’. > > > [-- Attachment #1.2: Type: text/html, Size: 3457 bytes --] [-- Attachment #2: unquote++.scm --] [-- Type: application/octet-stream, Size: 1237 bytes --] (define-module (syntax unquote++) #:export (quasisyntax++ insyntax)) (define *s* (make-fluid '())) (define (parse stx x) (syntax-case x (unsyntax insyntax unsyntax-splicing) ((unsyntax . _) x) ((unsyntax-splicing . _) x) ((insyntax ((p ...) c ...)) (with-syntax ((g (datum->syntax stx (gensym "g")))) (fluid-set! *s* (cons #'(g (lambda (x) (syntax-case x () ((_ p ...) (begin c ...))))) (fluid-ref *s*))) #'(g p ...))) ((x . l) (cons (parse stx #'x) (parse stx #'l))) (x #'x))) (define-syntax quasisyntax++ (lambda (x) (syntax-case x () ((_ y) (begin (fluid-set! *s* '()) (with-syntax ((statement (parse x #'y)) (lets (fluid-ref *s*))) #'(quasisyntax (let-syntax lets statement)))))))) (define (rg ch stream) (let ((x (read-char stream))) (cond ((eqv? x #\`) `(quasisyntax++ ,(read stream))) (#t (error "Wrong format of # reader extension"))))) (define (rg. ch stream) `(insyntax ,(read stream))) (read-hash-extend #\# rg) (read-hash-extend #\. rg.) ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2014-05-03 21:29 UTC | newest] Thread overview: 24+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-06-30 15:22 Enhancement to the syntax system? Stefan Israelsson Tampe 2012-07-02 19:28 ` Ludovic Courtès 2012-07-02 20:43 ` Stefan Israelsson Tampe 2012-07-02 22:41 ` Ludovic Courtès 2012-07-03 14:37 ` Stefan Israelsson Tampe 2012-07-03 21:33 ` Ludovic Courtès 2012-07-03 21:52 ` Stefan Israelsson Tampe 2012-07-04 7:47 ` Marijn 2012-07-04 8:04 ` Stefan Israelsson Tampe 2012-07-09 15:52 ` Ludovic Courtès 2012-07-09 17:40 ` Stefan Israelsson Tampe 2012-07-10 8:24 ` Ludovic Courtès 2012-07-10 13:35 ` Stefan Israelsson Tampe 2012-07-10 14:34 ` Marijn 2012-07-10 14:51 ` [racket-dev] " Eli Barzilay [not found] ` <20476.16781.257276.194149-a5nvgYPMCZcx/1z6v04GWfZ8FUJU4vz8@public.gmane.org> 2012-07-10 15:03 ` Matthew Flatt 2012-07-10 15:26 ` [racket-dev] " Ludovic Courtès 2012-07-10 15:44 ` Stefan Israelsson Tampe 2012-07-10 17:47 ` Stefan Israelsson Tampe 2012-07-10 16:48 ` Eli Barzilay 2014-05-03 21:29 ` Marijn Schouten (hkBst) 2012-07-10 15:44 ` Ryan Culpepper 2012-07-10 15:22 ` Ludovic Courtès 2012-07-10 7:36 ` Stefan Israelsson Tampe
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).