-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 04-01-12 22:50, Eli Barzilay wrote: > 11 hours ago, Marijn wrote: >> It took me a while to understand what you're saying here, but if >> I am not mistaken you're saying that the result of the >> macro-expansion is a function-application with `let*' (or >> `for/hash') in the function position. Then when #%app looks that >> name up in the environment it doesn't find anything and thus >> complains about it. What I would then expect is that it complains >> about an undefined variable `let*'. > > There is no such lookup at runtime. Your code *does* expand into > a `let*' (or to `for/hash' in the original case), it just expands > into a non-parenthesized reference to it, which invokes the macro > transformer with just the identifier -- same as if you'd write (+ > let* 3). > > >>> 5. And BTW, the reason it doesn't work is that the first >>> expansion gets to >>> >>> ((with-variables let*) (with-variables ((y 1))) >>> (with-variables 2)) >>> >>> and this form is not a macro -- so it's expanded as a function >>> call, >>> >>> (#%app ...same...) >>> >>> and the rest is obvious. >> >> It's not so obvious to me why this should degenerate into a >> function call; I'd say it depends on the result of >> (with-variables let*). > > This is not a kind of "degeneration". Here's a possibly simpler > to follow example: > > -> (define-syntax foo (syntax-rules () [(foo (x y z)) ((foo x) (foo > y) (foo z))] [(foo x) x])) -> (foo (+ 1 2)) 3 -> (foo (when 1 2)) ; > stdin:19:6: when: bad syntax in: when [,bt for context] > > Here's what happens when macro expansion sees (foo (+ 1 2)): > > 1. It recognizes it as a use of the `foo' macro, and calls your > expander which returns > > ((foo +) (foo 1) (foo 2)) > > 2. Since this is not a macro (it doesn't begin with a known (or > any) identifier), it (roughly) interprets it as a function call, > which in Racket means that you now have: > > (#%app (foo +) (foo 1) (foo 2))
Yes, this is the step I wonder at. Since foo is a macro (foo +) may expand into a reference to a macro. Why choose semantics that explicitly exclude/invalidate that case? If it turns out (foo +) doesn't expand to a reference to a macro isn't there still plenty of time to insert `#%app'? > At this point it's probably tempting to say that the `foo' macro > behaves well only when you hand it expressions that do not involve > macros. This is a dangerous assumption, since there might be > forms that look like plain applications but are really > macro-expanded -- like applying a contracted function (which is, > IIRC, implemented as a macro to give source information). In these > cases you'd lose such special treatment. This seems to be an artifact of the above choice to exclude certain possibilities. > But an even more subtle point is when you mix languages: the above > seemingly fine case of (foo (+ 1 2)) can be broken since it uses > whatever application means in whatever module the `foo' definition > appears at. If, for example, you use it in a language that has a > different meaning for applications (like the lazy language), then > the result will be confusing in that you'd get the meaning from > `foo's module. Idem ditto here. If you don't read `foo' as having an invisible #%app in its definition (lexically bound to whatever #%app is in that module), then this problem doesn't exist. Thanks for your other comments. Marijn -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk8Fgw8ACgkQp/VmCx0OL2zs5ACgoaapvYmWpFDjHJ+BLiI+W+rn rOMAoK4yYrX7p4s7z0agUJ+yUuzoznRV =2wdp -----END PGP SIGNATURE----- ____________________ Racket Users list: http://lists.racket-lang.org/users