From: Eli Barzilay <eli@barzilay.org>
To: Ryan Culpepper <ryan@cs.utah.edu>, Matthew Flatt <mflatt@cs.utah.edu>
Cc: "dev@racket-lang.org" <dev@racket-lang.org>,
"Ludovic Courtès" <ludo@gnu.org>,
guile-devel@gnu.org
Subject: Re: [racket-dev] Enhancement to the syntax system?
Date: Tue, 10 Jul 2012 12:48:04 -0400 [thread overview]
Message-ID: <20476.23748.668481.434218@winooski.ccs.neu.edu> (raw)
In-Reply-To: <20120710150315.B7B27650059@mail-svr1.cs.utah.edu>, <4FFC4DF3.8030203@cs.utah.edu>
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!
next prev parent reply other threads:[~2012-07-10 16:48 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20476.23748.668481.434218@winooski.ccs.neu.edu \
--to=eli@barzilay.org \
--cc=dev@racket-lang.org \
--cc=guile-devel@gnu.org \
--cc=ludo@gnu.org \
--cc=mflatt@cs.utah.edu \
--cc=ryan@cs.utah.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).