The concept is pretty opaque; syntax object contexts are a fairly tricky, black-magic part of the language. There is a rhyme and reason to them, but it isn't terribly high level or user-friendly. Sadly, no one yet knows how to do better for macros as powerful as Racket's. I've spent a long time with them, and I got the deepest understanding from reading Kent Dybvig's paper "Syntactic Abstraction in Scheme" over and over. And eventually implementing it myself, which was incidental but certainly made things crystal clear. I don't know that it's necessary to go that far to work with advanced macros; mostly, writing things with default hygiene as much as possible, and occasionally using syntax-local-introduce for tricky stuff like macros that produce units or require forms, will get you pretty far.
Carl Eastlund On Tue, Aug 6, 2013 at 5:57 PM, Nick Main <david.nick.m...@gmail.com> wrote: > Many thanks ! > > The problem makes sense and the solution works. > > Are there any explanations of "syntax marks" beyond those in the "Syntax > Model" section of the documentation ? The concept seems opaque. > > > On Tue, Aug 6, 2013 at 2:32 PM, Carl Eastlund <c...@ccs.neu.edu> wrote: > >> Nick, >> >> The unit system has some non-hygienic behavior, by design. That is, it >> introduces names that aren't part of its input, which isn't the default >> behavior of hygienic macros. Of course we want this -- we want the macro >> use-dog to bind the names woof and bark, which aren't directly part of its >> input. But getting the context right, and still "playing nice" with other >> hygienic macros, is slightly tricky. >> >> So in this context, what's the trick? The names bound by >> define-values/invoke-unit are bound in the context that the interface names >> are written in. Note that the interface names in use-dog are written >> inside the macro definition. The macro system assumes anything from inside >> a macro is a local or "temporary" name that should be hidden from the rest >> of the program. You can fix this with the syntax-local-introduce function, >> which (basically) toggles the context of a given syntax object between the >> current macro expansion step and its call site. >> >> So right now you are getting two definitions each for woof and bark, one >> visible by the main module and one only visible from the expansion of the >> use-dog macro. If you call use-dog multiple times, you'll get more, >> separate, unique contexts. >> >> You can fix it like this, to make use-dog bind things in the context >> where it is called: >> >> (define-syntax (use-dog stx) >> (syntax-case stx () >> ([_ dog-unit] >> #`(define-values/invoke-unit dog-unit >> (import) >> (export #,(syntax-local-introduce #'dog^)))))) >> >> Carl Eastlund >> >> On Tue, Aug 6, 2013 at 5:11 PM, Nick Main <david.nick.m...@gmail.com>wrote: >> >>> I am attempting to write a macro to clean up the use >>> of define-values/invoke-unit and finding some confusing behavior. >>> >>> My macros module is: >>> >>> #lang racket >>> (provide (all-defined-out)) >>> >>> (define-signature dog^ >>> (woof >>> bark)) >>> >>> (define mutt@ >>> (unit >>> (import) >>> (export dog^) >>> (define (woof) (printf "Wuf !!\n")) >>> (define (bark) (printf "RarRarRar !!\n")))) >>> >>> (define-syntax use-dog >>> (syntax-rules () >>> ([_ dog-unit] >>> (define-values/invoke-unit dog-unit >>> (import) >>> (export dog^))))) >>> >>> >>> ..and the module using it is: >>> >>> #lang racket >>> (require "macros.rkt") >>> >>> (define-values/invoke-unit mutt@ >>> (import) >>> (export dog^)) >>> >>> (use-dog mutt@) >>> >>> (woof) >>> (woof) >>> (bark) >>> (woof) >>> >>> >>> I am trying to make the "use-dog" macro expand to the equivalent >>> define-values/invoke-unit form as shown. >>> If I comment out the define-value/invoke-unit form I get warning about >>> unbound identifier woof - implying that the (use-dog dog^) form is not >>> doing the job. Moreover, the second module as it stands does not give a >>> warning about duplicate definitions for woof or bark (as it does if I >>> duplicate the define-values/invoke-unit form) - further indicating the >>> non-action of use-dog. >>> >>> The macro stepper shows use-dog expand exactly as expected, but it then >>> seems to be ignored without any warnings. >>> >>> Is there something I am misunderstanding here, or is this a bug ? >>> >>> ____________________ >>> Racket Users list: >>> http://lists.racket-lang.org/users >>> >>> >> >
____________________ Racket Users list: http://lists.racket-lang.org/users