unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
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!



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