From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Eli Barzilay Newsgroups: gmane.lisp.guile.devel,gmane.comp.lang.racket.devel Subject: Re: [racket-dev] Enhancement to the syntax system? Date: Tue, 10 Jul 2012 12:48:04 -0400 Message-ID: <20476.23748.668481.434218@winooski.ccs.neu.edu> References: <877gumufmq.fsf@gnu.org> <87r4stss4d.fsf@gnu.org> <878vf0o7gs.fsf@gnu.org> <87pq85dj8o.fsf@gnu.org> <87sjd058ia.fsf@gnu.org> <4FFC3D72.8070506@gentoo.org> <20476.16781.257276.194149@winooski.ccs.neu.edu> <4FFC4DF3.8030203@cs.utah.edu> <20120710150315.B7B27650059@mail-svr1.cs.utah.edu> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Trace: dough.gmane.org 1341938919 22178 80.91.229.3 (10 Jul 2012 16:48:39 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Tue, 10 Jul 2012 16:48:39 +0000 (UTC) Cc: "dev@racket-lang.org" , Ludovic =?utf-8?Q?Court=C3=A8s?= , guile-devel@gnu.org To: Ryan Culpepper , Matthew Flatt Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Tue Jul 10 18:48:37 2012 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Sodc4-0006X0-4K for guile-devel@m.gmane.org; Tue, 10 Jul 2012 18:48:36 +0200 Original-Received: from localhost ([::1]:46386 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sodc3-0006zw-2E for guile-devel@m.gmane.org; Tue, 10 Jul 2012 12:48:35 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:56476) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sodbq-0006w7-7e for guile-devel@gnu.org; Tue, 10 Jul 2012 12:48:32 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Sodbh-0004qE-B1 for guile-devel@gnu.org; Tue, 10 Jul 2012 12:48:21 -0400 Original-Received: from winooski.ccs.neu.edu ([129.10.115.117]:55196) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sodbh-0004pn-5J; Tue, 10 Jul 2012 12:48:13 -0400 Original-Received: from winooski.ccs.neu.edu (localhost.localdomain [127.0.0.1]) by winooski.ccs.neu.edu (8.14.4/8.14.4) with ESMTP id q6AGm5dY012359; Tue, 10 Jul 2012 12:48:05 -0400 Original-Received: (from eli@localhost) by winooski.ccs.neu.edu (8.14.4/8.14.4/Submit) id q6AGm4tV012354; Tue, 10 Jul 2012 12:48:04 -0400 In-Reply-To: <20120710150315.B7B27650059@mail-svr1.cs.utah.edu>, <4FFC4DF3.8030203@cs.utah.edu> X-Mailer: VM 8.2.0a under 23.2.1 (x86_64-redhat-linux-gnu) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 129.10.115.117 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:14735 gmane.comp.lang.racket.devel:6405 Archived-At: 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!