[racket] for/hash: bad syntax in: for/hash [and 1 more messages]
-----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-----