If I remember correctly, the difference is for historical reasons. Module-level partial expansion uses `local-expand` with a stop list, while internal-definition partial expansion uses `local-expand` with `#f` in place of a stop list. Those are not quite the same thing when `#%app` is bound to a macro. (Note that importing `#%plain-app` as `#%app` changes the results.)
This difference is surely not a good idea, and it reflects how we didn't know where we were going at first. Given that existing code probably relies on each behavior, though, it's probably not as simple as just picking one of the behaviors. Meanwhile, your example illustrates a definite bug, which is that (let () 8 (define-syntax-rule (m) 10)) is allowed and produces 8. There must be a check missing in the expander to ensure that an internal-definition sequence does not end with a syntax definition. (The old expander in v6.12 and earlier did not have this bug.) At Wed, 6 Mar 2019 22:01:47 -0800 (PST), Milo Turner wrote: > I was discussing with a friend some of the edge cases in how internal > definition contexts and expansion > work, when I accidentally ran into behavior that doesn't seem right. > > (let () > (foo) > (define-syntax-rule (define-it m) > (define-syntax (m stx) #'"hello!")) > (define-it foo)) > > ;; -> "hello!" > > (begin > (foo) > (define-syntax-rule (define-it m) > (define-syntax (m stx) #'"hello!")) > (define-it foo)) > > ;; application: not a procedure; > ;; expected a procedure that can be applied to arguments > ;; given: "hello!" > > Both cases are of course predicated on the behavior of > internal-definition-contexts passing over unbound > identifiers twice to see if they "became" a macro by the time the > definition context has been fully > populated. I know the semantics here are pretty quirky and up for debate, > but I don't think that this is > the expected behavior in any case. What seems to be happening precisely is > that when "foo" is expanded > in a local definition context, the parenthesis are given to the transformer > procedure (#'(foo)), versus if it is > expanded in a module begin context, only the identifier is given to the > transformer procedure (#'foo), and > then the parenthesis are added on afterwards. > > ;; if in local definition context: > (f . args) ==> (#%expression (f . args)) > ;; if in module begin context (BAD!): > (f . args) ==> ((#%expression f) . args) > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.