By the way, I found that this also works - applying the lexical context of the dog-unit syntax-object to the dog^ identifier:
(define-syntax (use-dog stx) (syntax-case stx () ([_ dog-unit] #`(define-values/invoke-unit dog-unit (import) (export #,(datum->syntax #'dog-unit 'dog^)))))) Again, many thanks. 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